Closed StephanMeijer closed 4 years ago
Hi @StephanMeijer,
That's very interesting. It has been my experience that Tuya devices will only allow one connection at a time, which means that when the app is running tuyapower
will return with an error. The devicePrint()
function doesn't cache any of the data (it actually sets all the values to -99 before polling), so if it is displaying any data, that is coming back from the smartplug itself. In the example you give, it seems like the smartplug is providing data even when the app is running but it does look like it is not updating over time (is that true?).
If you stop the app and keep it off for >5 minutes, are you able to get tuyapower
to give you correct and changing data? In my experience, for the 3.1 and 3.3 plugs I have, even after sopping the app I have to wait a while before the smartplug start responding with valid data. Alternatively, I suppose there could be some key/authentication issue.
Try running something like this for several minutes (with the app closed) to see what happens:
import time
import tuyapower
PLUGID = '01234567891234567890'
PLUGIP = '10.0.1.99'
PLUGKEY = '0123456789abcdef'
PLUGVERS = '3.3'
while True:
tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
time.sleep(5)
Sorry @jasonacox. I was so annoyed, I sent the product back. Now switched to the TP-Link HS-110.
Thanks for the update @StephanMeijer - Let me know how the TP-Link HS_110 works for you.
Hi @jasonacox, I am experiencing the exact same thing with the Denver SHP-100's I have.
It seems like it just always send back the latest of a cached value, and only update the cache when opening the Smart Life / Tuya app.
Any ideas?
Update: It seems like if I let it run for 5-10 minutes (without opening any Tuya app) then sometimes it will update the value once and then keep that value for the next 5-10 minutes. Other times I can let it run for an hour with no update.
Hi @Bjarkes - this happens with some plugs.
1) When SmartLife app is running, the Tuya device will reject all other attempts to connect to it. That is why tuyapower stops working when you run the app.
2) Some plugs require an UPDATEDPS command to update their power data points immediately, otherwise they cache as you noted.
Here is an example:
import tinytuya
import time
# Connect to the device - replace with real values
d=tinytuya.OutletDevice(DEVICEID, DEVICEIP, DEVICEKEY)
d.set_version(3.3)
# Option for Power Monitoring Smart Plugs - Some require UPDATEDPS to update power data points
payload = d.generate_payload(tinytuya.UPDATEDPS,['18','19','20'])
d.send(payload)
sleep(1)
# Get the status of the device
# e.g. {'devId': '0071299988f9376255b', 'dps': {'1': True, '3': 208, '101': False}}
data = d.get_status()
print(data)
You can also try this script to monitor the plug and see if you are getting more frequent power updates:
# TinyTuya Example
# -*- coding: utf-8 -*-
"""
TinyTuya - Example showing async persistent connection to device with
continual loop watching for device updates.
Author: Jason A. Cox
For more information see https://github.com/jasonacox/tinytuya
"""
import tinytuya
# tinytuya.set_debug(True)
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 keepalive heartbeat
print(" > Send Heartbeat Ping < ")
payload = d.generate_payload(tinytuya.HEART_BEAT)
d.send(payload)
# Option - Some plugs require an UPDATEDPS command to update their power data points
print(" > Send Request for Status < ")
payload = d.generate_payload(tinytuya.DP_QUERY)
d.send(payload)
# See if any data is available
data = d.receive()
print('Received Payload: %r' % data)
print(" > Send DPS Update Request < ")
payload = d.generate_payload(tinytuya.UPDATEDPS,['18','19','20'])
d.send(payload)
# See if any data is available
data = d.receive()
print('Received Payload: %r' % data)
Hi @jasonacox, thank you for you reply
I tested both scripts, with no success. One thing I noticed is that if I run the "script to monitor" and then open the Smart Life app, then I get all the updates, but as soon as I close down the app it goes back to receiving the same response again and again. I wonder what kind of signal the app is sending to trigger the updates.
Here is an output sample, you can see that I got different payload and in the bottom I start to get the same after I closed down the app.
> Send Request for Status <
Received Payload: None
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 109, '19': 206, '20': 2290, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 111, '19': 196}, 't': 1627030593}
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 111, '19': 196, '20': 2290, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 102, '19': 202}, 't': 1627030598}
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: None
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 112, '19': 210, '20': 2294, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 106, '19': 193}, 't': 1627030609}
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 106, '19': 193, '20': 2294, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 111, '19': 197, '20': 2290}, 't': 1627030613}
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 101, '19': 193}, 't': 1627030618}
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 111, '19': 192}, 't': 1627030623}
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: None
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 110, '19': 198, '20': 2286, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 121, '19': 218}, 't': 1627030633}
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 121, '19': 218, '20': 2286, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 119, '19': 204, '20': 2290}, 't': 1627030638}
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 104, '19': 235}, 't': 1627030643}
> Send DPS Update Request <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'18': 129, '19': 192, '20': 2286}, 't': 1627030648}
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: None
> Send DPS Update Request <
Received Payload: None
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 103, '19': 217, '20': 2286, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: None
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 103, '19': 217, '20': 2286, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: None
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 103, '19': 217, '20': 2286, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: None
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 103, '19': 217, '20': 2286, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: None
Received Payload: None
> Send Heartbeat Ping <
> Send Request for Status <
Received Payload: {'devId': '71316800c82b966a7efb', 'dps': {'1': True, '9': 0, '18': 103, '19': 217, '20': 2286, '21': 1, '22': 634, '23': 34366, '24': 19950, '25': 1044}}
> Send DPS Update Request <
Received Payload: None
Received Payload: None
After hours of investigation and even trying our other libraries (including Tuya's own) with no luck, always the same behavior, I found the solution.
It all comes down to how the generate_payload method with the UPDATEDPS command is called. If I remove the data and just write generate_payload(tinytuya.UPDATEDPS)
then it works perfectly, but with the data like in your example: generate_payload(tinytuya.UPDATEDPS,['18','19','20'])
it just return None, unless I have the "Electric" tab open for the device in the Smart Life app.
It must be some kind of bad implementation in their end I suppose. Their own tools like api, sdk and add-ons (like fx. the tuya 2 for Home Asssistant) does not work either unless the app is used as described or now with my tinytuya loop.
Nice find!! I want to add a note to my example script for that use case. Can you send me the script you used that worked? Was it basically this?
print(" > Send DPS Update Request < ")
payload = d.generate_payload(tinytuya.UPDATEDPS)
d.send(payload)
If so, that is equivalent to:
print(" > Send DPS Update Request < ")
payload = d.generate_payload(tinytuya.UPDATEDPS,[1])
d.send(payload)
It could also be an issue with that Tuya device not accepting quoted DPS index values in the JSON payload. This may also work:
print(" > Send DPS Update Request < ")
payload = d.generate_payload(tinytuya.UPDATEDPS,[18,19,20])
d.send(payload)
It would be interesting to see what works for you. :)
Thanks for the update!
Yes, your first example is basically what works, I just run that in a loop and then I get updated status values every 5 second or so.
The last example also works, that is d.generate_payload(tinytuya.UPDATEDPS,[18,19,20])
, so it seems like the device does not accept quoted DPS index values as you suggested.
But the d.generate_payload(tinytuya.UPDATEDPS,[1])
is not equivalent to no data input, using that it gives no updates as before. Looking at the tinytuya source code, it actually looks like the default is [18,19,20]
without quotes. The payload_dict["default"] has:
UPDATEDPS: {
"hexByte": "12",
"command": {"dpId": [18, 19, 20]}
},
Feel free to come with more suggestions on what to test, the more we learn and can share, the less other people have to waste time scratching their head like I did.
I was going crazy... VERY THANKS to the last 2 comments!
Using Denver SHP-100, testing with waterboiler.
After closing app and turning off boiler:
After opening app:
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.