Open Titriel opened 3 months ago
Hi @Titriel - Can you give an example of your code? I think what you want is something like:
import tinytuya
# Connect
d = tinytuya.OutletDevice(id, ip, key, version="3.3")
# Set value of DPS index 25
d.set_value(25, 'xyz')
# Read value
data = d.status()
setting = data['dps']['25']
print(setting)
@jasonacox Thank you very mutch for your answer. But this is that what I not want do do. Because I have to sent a second request to the device. I have seen, it is possibel to do settings about retrys by setting up the OutletDevice eg. So I think you had figured out a posibility to check if a retry is needed or not. I think, if a request to the device ist sucsessfully, you stop retreying. Or did you only send the request n times in the maner of fire and forget ? If you do fire and forget, that what I request to you is not posible. But if the device sands in any way an aknowlage back to an request, it should be posible eg. to return true by the call d.set_value if the device had aknowlaged and false if it has not aknowlaged over all retrys. If that will be posible, it makes sence do do this kind of return by all devices requsting calls.
Sorry for my terible english, it's not my native language.
Hi @Titriel - the commands wait for a response by default. You would need to set nowait=True
for it to send only without waiting for a ACK response.
set_value(index, value, nowait=False)
The set_value()
function calls __send_receive(()
which has logic to retry up to the socketRetryLimit
amount and as long as the retry
setting is set globally (default is True).
For your use case, you just need to make sure you get a valid response:
response = d.set_value("1",True)
# Should get eomething like: {'devId': 'abcdefg1234567', 'dps': {'1': True}, 't': 1712501649}
if "dps" in response:
print("Updated")
else:
print("Failed")
If you are curious, you can see how TinyTuya handles it in the core code here:
Thank you very mutch. I check it out.
Unfortunately TinyTuya doesn't really handle command success/fail well. This is a good candidate for an enhancement. Let's take a step back and look at all the possible command results:
The results for each might be unexpected:
1 will return an ERR_JSON object after the retry limit is reached.
2/5/7 will be counted as "success" and return that update.
3 will return an ERR_JSON about decoding the response.
4/6 will be counted as "success" and return None
.
Instead of the above, we should probably be checking the retcode and immediately return an ERR_JSON if it's bad. Making sure we get a good retcode for the command we sent would be an additional check but brings up the issue of what to do with async updates received before the command response.
For now the only way to make sure we have success is to do something like:
d.set_value("1", True, nowait=True)
d.set_retry(False)
resp = d._send_receive(None, decode_response=False)
while resp and resp.cmd != [sent command]:
resp = d._send_receive(None, decode_response=False)
d.set_retry(True)
if resp and resp.retcode == 0:
print('Success!')
else:
print('Failed!')
Unfortunately there's no good way of getting the exact command sent as it can be remapped based on the device quirks. Another TinyTuya enhancement could be to return the exact TuyaMessage sent when nowait=True
.
Hi, I am on creating an universal MQTT- Adapter. I was able to add your tinytuya class in my Adapter, and it works fine. Some devices are hard on the border of the range of my WIFI. So it would be helpfull, that calls like set_value, sends back if it was successtull sending data to the device. Or is there a way how I can requst this state ?
Thank You