jasonacox / tinytuya

Python API for Tuya WiFi smart devices using a direct local area network (LAN) connection or the cloud (TuyaCloud API).
MIT License
933 stars 166 forks source link

It only works when I make calls from SmartLife - LSC Smart Connect Bulb #99

Open Hugo-prod opened 2 years ago

Hugo-prod commented 2 years ago

The command sent to my bulb only works when I send an action from SmartLife.

d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY) d.set_version(3.3) DEBUG:status() entry (devtype is default) DEBUG:building payload=b'{"gwId":"bfaec9ff095b9719bf5oalt","devId":"bfaec9ff095b9719bf5oalt","uid":"bfaec9ff095b9719bf5oalt","t":"1642103022"}' DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x88\xff\x0c\xb8\xf5+\x91\xbcIWqla<\x80\x1e\x84\xf9t)\xe4\xf1\x9b\x8d\xa6\xff\xa8\xc1\x89e3m\xa3\x832\xf5\x96\xd5\xea9`\xf1\xc2\xf5\xec[\xdf#Y\x8a\xa0\xf2\x03\x92\xed\xac\x8a\xb8z\xee\n~\x13&\x84\xa4\x16&\xefs(\x88\x03q\x1f\xb7\xb7\xde\xccSY\x8a\xa0\xf2\x03\x92\xed\xac\x8a\xb8z\xee\n~\x13&\xdb\xc3\xb0J8\xcd\xf8\xf4\xf2\xf5_\xe8J\xa8\xe1\x85\x05\x15\xfe\x17\x15\x7fp\x93\x9f\x1a\x99\xc1u=\xf2n\x05\xcf\xac<\x00\x00\xaaU' DEBUG:received data=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00,\x00\x00\x00\x01,\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe\x90\x05\x02\xea\x00\x00\xaaU' DEBUG:raw unpacked message = TuyaMessage(seqno=0, cmd=10, retcode=1, payload=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe', crc=2416247530) DEBUG:decode payload=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe' DEBUG:decrypting=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe' DEBUG:decrypted 3.3 payload='json obj data unvalid' DEBUG:payload type = <class 'str'> DEBUG:'data unvalid' error detected: switching to dev_type 'device22' DEBUG:Device22 detected and updated (default -> device22) - Update payload and try again DEBUG:ERROR Device22 Detected: Retry Command - 908 - payload: null DEBUG:status() received data={'Error': 'Device22 Detected: Retry Command', 'Err': '908', 'Payload': None} DEBUG:status() rebuilding payload for device22 DEBUG:building payload=b'{"devId":"bfaec9ff095b9719bf5oalt","uid":"bfaec9ff095b9719bf5oalt","t":"1642103022","dps":{"1":null}}' DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x873.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90y3g0\x93G(ax\xd9}B\xf7\x02\xb3\xd1/\\x11\xc8\xd8]\xf4\xb9a\xbaD\xe6&\xf1\xef\x7fK\x88\t\xa6-\xc6>3\xca\x8aG\xe7Q\r#\x05\xa1\x81\x87\xbe\x00\x00\xaaU' DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one DEBUG:Timeout or exception in _send_receive() - retry 1/5 DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one DEBUG:Timeout or exception in _send_receive() - retry 2/5 DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one DEBUG:Timeout or exception in _send_receive() - retry 3/5 DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one DEBUG:Timeout or exception in _send_receive() - retry 4/5 DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one DEBUG:Timeout or exception in _send_receive() - retry 5/5 DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one DEBUG:Timeout or exception in _send_receive() - retry 6/5 DEBUG:Exceeded tinytuya retry limit (5) DEBUG:ERROR Timeout Waiting for Device - 902 - payload: "Check device key or version" DEBUG:bulb type set to B

d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY) d.set_version(3.3) DEBUG:status() entry (devtype is default) DEBUG:building payload=b'{"gwId":"bfaec9ff095b9719bf5oalt","devId":"bfaec9ff095b9719bf5oalt","uid":"bfaec9ff095b9719bf5oalt","t":"1642103392"}' DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x88\xff\x0c\xb8\xf5+\x91\xbcIWqla<\x80\x1e\x84\xf9t)\xe4\xf1\x9b\x8d\xa6\xff\xa8\xc1\x89e3m\xa3\x832\xf5\x96\xd5\xea9`\xf1\xc2\xf5\xec[\xdf#Y\x8a\xa0\xf2\x03\x92\xed\xac\x8a\xb8z\xee\n~\x13&\x84\xa4\x16&\xefs(\x88\x03q\x1f\xb7\xb7\xde\xccSY\x8a\xa0\xf2\x03\x92\xed\xac\x8a\xb8z\xee\n~\x13&\xdb\xc3\xb0J8\xcd\xf8\xf4\xf2\xf5_\xe8J\xa8\xe1\x85r\xf8\x06\x01C\xe3\x9a\x7f\xfeK\xf9x\xfe\xdcd\xf6\xa2\xbe\xf2\xf4\x00\x00\xaaU' DEBUG:received data=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00,\x00\x00\x00\x01,\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe\x90\x05\x02\xea\x00\x00\xaaU' DEBUG:raw unpacked message = TuyaMessage(seqno=0, cmd=10, retcode=1, payload=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe', crc=2416247530) DEBUG:decode payload=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe' DEBUG:decrypting=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe' DEBUG:decrypted 3.3 payload='json obj data unvalid' DEBUG:payload type = <class 'str'> DEBUG:'data unvalid' error detected: switching to dev_type 'device22' DEBUG:Device22 detected and updated (default -> device22) - Update payload and try again DEBUG:ERROR Device22 Detected: Retry Command - 908 - payload: null DEBUG:status() received data={'Error': 'Device22 Detected: Retry Command', 'Err': '908', 'Payload': None} DEBUG:status() rebuilding payload for device22 DEBUG:building payload=b'{"devId":"bfaec9ff095b9719bf5oalt","uid":"bfaec9ff095b9719bf5oalt","t":"1642103392","dps":{"1":null}}' DEBUG:payload generated=b"\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x873.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\xf9\xc4@\xa6g\xcd\x07\xfc\x1b\xcb}c\x8b'a\xa0\xb5U\xe1V9p(K\xa7\xc3h\6<DfK\x88\t\xa6-\xc6>3\xca\x8aG\xe7Q\r#\x05)\xc3\x02C\x00\x00\xaaU" DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one DEBUG:received data=b"\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00K\x00\x00\x00\x003.3\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x01'/2\xa6k\xda\xaf\x06#\xed.\x1cuO\x85\x82\x01~\xe3=4B\x8c\x80\xd0\x1a\xfb\x88\xaa\xc7\xb1\xc8\xee,\x01\xeaZ>H\xd8#\xa1H\xa49\xdfWT\xc8;\xa9o\x00\x00\xaaU" DEBUG:raw unpacked message = TuyaMessage(seqno=0, cmd=8, retcode=0, payload=b"3.3\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x01'/2\xa6k\xda\xaf\x06#\xed.\x1cuO\x85\x82\x01~\xe3=4B\x8c\x80\xd0\x1a\xfb\x88\xaa\xc7\xb1\xc8\xee,\x01\xeaZ>H\xd8#\xa1H\xa49\xdfWT", crc=3359353199) DEBUG:decode payload=b"3.3\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x01'/2\xa6k\xda\xaf\x06#\xed.\x1cuO\x85\x82\x01~\xe3=4B\x8c\x80\xd0\x1a\xfb\x88\xaa\xc7\xb1\xc8\xee,\x01\xeaZ>H\xd8#\xa1H\xa49\xdfWT" DEBUG:removing 3.3=b"'/2\xa6k\xda\xaf\x06#\xed.\x1cuO\x85\x82\x01~\xe3=4B\x8c\x80\xd0\x1a\xfb\x88\xaa\xc7\xb1\xc8\xee,\x01\xeaZ>H\xd8#\xa1H\xa49\xdfWT" DEBUG:decrypting=b"'/2\xa6k\xda\xaf\x06#\xed.\x1cuO\x85\x82\x01~\xe3=4B\x8c\x80\xd0\x1a\xfb\x88\xaa\xc7\xb1\xc8\xee,\x01\xeaZ>H\xd8#\xa1H\xa49\xdfWT" DEBUG:decrypted 3.3 payload='{"dps":{"1":false},"t":1642103390}' DEBUG:payload type = <class 'str'> DEBUG:decoded results='{"dps":{"1":false},"t":1642103390}' DEBUG:bulb type set to A

jasonacox commented 2 years ago

Hi @Hugo-prod - thanks for opening the Issue with debug. I will edit your post to remove the ID and KEY for security.

Can you post a link the type of Bulb you are using?

Some things you might try:

Try 1 - Device22

You can update your script to specify device22 upfront instead of having tinytuya detect and reissue commands:

  d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY, 'device22')
  d.set_dpsUsed({"1": None})  # This needs to be a datapoint available on the device
  d.set_version(3.3)
  data =  d.status()
  print(data)

Try 2 - Add Retry

Try running the set_version(3.3) twice if it fails the first time:

  d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
  d.set_version(3.3)
  # try again
  d.set_version(3.3)
Hugo-prod commented 2 years ago

Hello @jasonacox :)

Here is all the information I can give (And especially to add keywords for future research on the same object as me)

The bulb in question is a low-cost bulb bought from a French retailer It is rebranded under the name of LSC Smart Connect

It's exactly this one https://www.action.com/fr-fr/p/ampoule-led-multicolore-connectee-lsc-smart-connect-2/

Upload the box of the bulb in case the link to the article broke in the future: LSC_SMART_Connect_A60_RGB-CCT

I don't know where I found this information, but apparently it is identified under this name: LSC SMART Connect A60 RGB-CCT (as I was writing this, the problem could be with the SmartLife or LSC Smart Connect application ?)

Other information: The seller of this bulb did some rebranding, and generated a new app with its own packaging, the basic app for the bulb is this: LSC Smart Connect https://play.google.com/store/apps/details?id=com.lscsmartconnection.smart&hl=en&gl=US As I went along I realized that this application was in fact this application but with a rebranding wrapper: Smart Life https://play.google.com/store/apps/details?id=com.tuya.smartlife&hl=en&gl=US So I uninstalled LSC Smart Connect and installed Smart Life, then paired my bulb with this application (Now that I wrote this, could my problem come from there?)


Result - Try 1 Device22:


Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tinytuya
>>> tinytuya.set_debug(True)
DEBUG:TinyTuya [1.3.1]

>>> d = tinytuya.BulbDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY', 'device22')
>>> d.set_dpsUsed({"1": None})
>>> d.set_version(3.3)
DEBUG:status() entry (dev_type is device22)
DEBUG:building payload=b'{"devId":"DEVICEID","uid":"DEVICEID","t":"1642172775","dps":{"1":null}}'
DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x873.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\xba\xbc\x03\xa7\x8f\xa3\xb2EM\xe9\x0b\xb3\x91\xc3moW\x03\x03&\x10q\x81\x7f\x8c\xe3W\xc7\x98\x8a\xd7\xe7K\x88\t\xa6-\xc6>3\xca\x8aG\xe7Q\r#\x05\xe5VH\x1f\x00\x00\xaaU'
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 1/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 2/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 3/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 4/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 5/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 6/5
DEBUG:Exceeded tinytuya retry limit (5)
DEBUG:ERROR Timeout Waiting for Device - 902 - payload: "Check device key or version"
DEBUG:status() received data={'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}
DEBUG:bulb type set to B
>>> data =  d.status()
DEBUG:status() entry (dev_type is device22)
DEBUG:building payload=b'{"devId":"DEVICEID","uid":"DEVICEID","t":"1642172813","dps":{"1":null}}'
DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x873.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x19\xc7x\x07\xadu\xa7\x00$y {\x99\x8bL\xff\xd3h\x88:\x1c$.\xbc?\xbc\xb0_Z\xb5%\xc5K\x88\t\xa6-\xc6>3\xca\x8aG\xe7Q\r#\x05@D{0\x00\x00\xaaU'
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 1/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 2/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 3/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 4/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 5/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 6/5
DEBUG:Exceeded tinytuya retry limit (5)
DEBUG:ERROR Timeout Waiting for Device - 902 - payload: "Check device key or version"
DEBUG:status() received data={'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}
>>> print(data)
{'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}
>>>

Result - Try 2 Retry:

Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tinytuya
>>> tinytuya.set_debug(True)
DEBUG:TinyTuya [1.3.1]

>>> d = tinytuya.BulbDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY')
>>> d.set_version(3.3)
DEBUG:status() entry (dev_type is default)
DEBUG:building payload=b'{"gwId":"DEVICEID","devId":"DEVICEID","uid":"DEVICEID","t":"1642173098"}'
DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x88\xff\x0c\xb8\xf5+\x91\xbcIWqla<\x80\x1e\x84\xf9t)\xe4\xf1\x9b\x8d\xa6\xff\xa8\xc1\x89e3m\xa3\x832\xf5\x96\xd5\xea9`\xf1\xc2_\xf5\xec[\xdf#Y\x8a\xa0\xf2\x03\x92\xed\xac\x8a\xb8z\xee\n~\x13&\x84\xa4\x16&\xefs(\x88\x03q\x1f\xb7\xb7\xde\xccSY\x8a\xa0\xf2\x03\x92\xed\xac\x8a\xb8z\xee\n~\x13&\x03\xa9_\x19<\xe5\xbcZ\xa3,\xce\x895`glEr\x90\x94v-\xe58\x89\x95.\xc5\xd1\x81\xe3>m\xb9\xd7\x82\x00\x00\xaaU'
DEBUG:received data=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00,\x00\x00\x00\x01,\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe\x90\x05\x02\xea\x00\x00\xaaU'
DEBUG:raw unpacked message = TuyaMessage(seqno=0, cmd=10, retcode=1, payload=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe', crc=2416247530)
DEBUG:decode payload=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe'
DEBUG:decrypting=b',\xc3\x9f\xcb\xd7\xbd{\x1d\x86\xa4\x07\xb8\xb3\x0e\xae\xba\xfa\x16\xd1\xcc\xce\xff\xd6d\xd7\x82{\x10\xe6\x11\xdb\xbe'
DEBUG:decrypted 3.3 payload='json obj data unvalid'
DEBUG:payload type = <class 'str'>
DEBUG:'data unvalid' error detected: switching to dev_type 'device22'
DEBUG:Device22 detected and updated (default -> device22) - Update payload and try again
DEBUG:ERROR Device22 Detected: Retry Command - 908 - payload: null
DEBUG:status() received data={'Error': 'Device22 Detected: Retry Command', 'Err': '908', 'Payload': None}
DEBUG:status() rebuilding payload for device22
DEBUG:building payload=b'{"devId":"DEVICEID","uid":"DEVICEID","t":"1642173098","dps":{"1":null}}'
DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x873.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\xd7:\xd1\xb1\x9a\xd9/\x89\x80\xcd\x92B\xe8\xfe\xab\x05\x9d\xc3=\xcd\x7f\x08\xb4\xa0\xf2\x1fX\xdb&\xec*)K\x88\t\xa6-\xc6>3\xca\x8aG\xe7Q\r#\x05r\x99\x8aQ\x00\x00\xaaU'
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 1/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 2/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 3/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 4/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 5/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 6/5
DEBUG:Exceeded tinytuya retry limit (5)
DEBUG:ERROR Timeout Waiting for Device - 902 - payload: "Check device key or version"
DEBUG:bulb type set to B
>>>   d.set_version(3.3)
  File "<stdin>", line 1
    d.set_version(3.3)
IndentationError: unexpected indent
>>> d.set_version(3.3)
DEBUG:status() entry (dev_type is device22)
DEBUG:building payload=b'{"devId":"DEVICEID","uid":"DEVICEID","t":"1642173151","dps":{"1":null}}'
DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x02\x00\x00\x00\r\x00\x00\x00\x873.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\xd8\x1e\xa2\x1c\\\xdb\x1b\x19\x15\xbf\xdcM\xfd\xfe\xe2"\xbe\xab\xc1\xee\xa9\xbdf\xe8,g\x89\xbf\xe7\xaaMdK\x88\t\xa6-\xc6>3\xca\x8aG\xe7Q\r#\x05\xdb\xb8:\x0b\x00\x00\xaaU'
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x02\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\x8d\xe1OD\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 1/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x02\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\x8d\xe1OD\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 2/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x02\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\x8d\xe1OD\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 3/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x02\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\x8d\xe1OD\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 4/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x02\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\x8d\xe1OD\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 5/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x02\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\x8d\xe1OD\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 6/5
DEBUG:Exceeded tinytuya retry limit (5)
DEBUG:ERROR Timeout Waiting for Device - 902 - payload: "Check device key or version"
DEBUG:status() received data={'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}
DEBUG:bulb type set to B
>>>

Result - Try 3 Retry with device22

Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tinytuya
>>> tinytuya.set_debug(True)
DEBUG:TinyTuya [1.3.1]

>>> d = tinytuya.BulbDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY', 'device22')
>>> d.set_version(3.3)
DEBUG:status() entry (dev_type is device22)
DEBUG:building payload=b'{"devId":"DEVICEID","uid":"DEVICEID","t":"1642173346","dps":{}}'
DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00w3.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x909\x81Y\x8d\x18\xa6\xa6\xf6\xf9sL\xefwLB\xf0\xc7!v\x14C{+w\x17\xa4^m/\x91N1\x18q\x01\x0c\x00\x00\xaaU'
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 1/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 2/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 3/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 4/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 5/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x00\xed\xbd\xfa\x0f\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 6/5
DEBUG:Exceeded tinytuya retry limit (5)
DEBUG:ERROR Timeout Waiting for Device - 902 - payload: "Check device key or version"
DEBUG:status() received data={'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}
DEBUG:bulb type set to B
>>> d.set_version(3.3)
DEBUG:status() entry (dev_type is device22)
DEBUG:building payload=b'{"devId":"DEVICEID","uid":"DEVICEID","t":"1642173383","dps":{}}'
DEBUG:payload generated=b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00w3.3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x02\x01\x13\xc9\xd5a\xb6B6\xa7q\xee\xb4\x95\xe9\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x90\x85\xa52\xe3\x15#9\xe6\x1f,xTn\xc6K\x84\xa5\xa6w\x16\xd1\x83\x98\xbbM1d\xec\xf5\x1a:\x909\x81Y\x8d\x18\xa6\xa6\xf6\xf9sL\xefwLB\xf0I\x94\xed\x15\x84f\xb0\x94\xa2r\xa4\xb2\x13AX\x15\xb6 C\x92\x00\x00\xaaU'
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 1/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 2/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 3/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 4/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 5/5
DEBUG:received null payload (b'\x00\x00U\xaa\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x0c\x00\x00\x00\x000+#\x8a\x00\x00\xaaU'), fetch new one
DEBUG:Timeout or exception in _send_receive() - retry 6/5
DEBUG:Exceeded tinytuya retry limit (5)
DEBUG:ERROR Timeout Waiting for Device - 902 - payload: "Check device key or version"
DEBUG:status() received data={'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}
DEBUG:bulb type set to B
>>>

Can you explain to me what DPS Data points are? I will try to pair my bulb with the rebranding application(LSC Smart Connect) to see if I have any change

Hugo-prod commented 2 years ago

I tried to re-pair the device with the default application (LSC Smart Connect), but I can't link my account with this application on iot.tuya

So only with Smart Life apk can I get the credentials

jasonacox commented 2 years ago

Yes, it is my understanding that only "Smart Life" and "Tuya Smart" apps will link with the iot.tuya.com site.

One more idea if you want to try... let's see what happens if you just connect to the device and listen for updates:

import tinytuya

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

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

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

    # Send keyalive heartbeat
    print(" > Send Heartbeat Ping < ")
    payload = d.generate_payload(tinytuya.HEART_BEAT)
    d.send(payload)
Hugo-prod commented 2 years ago

Ok, yes can test with pleasure Ok, I don't know if it's voluntary or not, but you declared my Bulb as an Outlet, so in doubt I did the test with Outlet and Bulb class

Test with Outlet()

> Send Request for Status <
> Begin Monitor Loop <
Received Payload: {'Error': 'Device22 Detected: Retry Command', 'Err': '908', 'Payload': None}
> Send Heartbeat Ping <
Received Payload: None
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 116}, 't': 1643052069}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 145}, 't': 1643052069}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 145}, 't': 1643052069}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 97}, 't': 1643052071}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 71}, 't': 1643052071}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 71}, 't': 1643052071}
> Send Heartbeat Ping <
Received Payload: {'dps': {'2': 'colour'}, 't': 1643052074}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': 'ff00150163ffff'}, 't': 1643052075}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': 'ff00f7012dffff'}, 't': 1643052076}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': '0004ff00efffff'}, 't': 1643052077}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': '00f9ff00b5ffff'}, 't': 1643052077}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': '75ff00005cffff'}, 't': 1643052077}

Test with Bulb()

> Send Request for Status <
> Begin Monitor Loop <
Received Payload: {'dps': {'3': 150}, 't': 1643051716}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 201}, 't': 1643051718}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 127}, 't': 1643051718}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 78}, 't': 1643051719}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 52}, 't': 1643051720}
> Send Heartbeat Ping <
Received Payload: {'dps': {'1': False}, 't': 1643051722}
> Send Heartbeat Ping <
Received Payload: {'dps': {'1': True}, 't': 1643051726}
> Send Heartbeat Ping <
Received Payload: {'dps': {'2': 'colour'}, 't': 1643051729}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': 'ff00d70135ffff'}, 't': 1643051732}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': '4700ff0100ffff'}, 't': 1643051733}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': '00fffe00b3ffff'}, 't': 1643051734}
> Send Heartbeat Ping <
Received Payload: {'dps': {'5': '36ff00006bffff'}, 't': 1643051735}
> Send Heartbeat Ping <
Received Payload: {'dps': {'2': 'white'}, 't': 1643051740}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 77}, 't': 1643051745}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 193}, 't': 1643051745}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 255}, 't': 1643051746}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 179}, 't': 1643051746}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 163}, 't': 1643051746}
> Send Heartbeat Ping <
Received Payload: {'dps': {'3': 163}, 't': 1643051746}

What version of Python are you using with your devices ? (3.5, 3.7, 3.9), in my case i use 3.9

jasonacox commented 2 years ago

Interesting results! You are getting valid updates from the Bulb. When using raw functions, send() and receive() you can use either class as you saw. It is interesting that the DPS (data points) coming back from bulb all look like a Bulb type "A" : https://github.com/jasonacox/tinytuya#version-31---light-type-rgb :

The autodetection was selecting Bulb type "B" because it wasn't getting a valid status answer from the Bulb. A workaround would be to manually set the Bulb type to "A":

d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY, 'device22')
  d.set_dpsUsed({"1": None}) 
  d.set_version(3.3)
  data =  d.status()
  # Force type to A
  d.bulb_type = 'A'

I'm on Python 3.8.9 and the CI tests with Python 2.7, 3.5, 3.6, 3.7 and 3.8.

mafrosis commented 2 years ago

Just adding a minor data point, as I was seeing the Retry Command - 908 - payload: null message which led me to this issue.

If my tuya fans are without internet for several days, they become unresponsive and start returning this error. If I re-enable internet access, allow them to talk to the cloud briefly, and then disable internet, all becomes normal.

Interestingly when the Retry Command - 908 - payload: null is presenting, I can control the fans via localtuya, but I get an error on the response. The fans are controllable but do respond correctly!

jasonacox commented 2 years ago

HI @mafrosis - thanks for the data point. The 908 error means that it actually got back a data unvalid response from the Tuya device, which is odd but as you observed. Likely a bug in the device that surfaced because it couldn't phone home.

I would be interested to know what you see when you get into that situation and run a script like this:

import tinytuya

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

print(" > Send Turn Off Command <")
payload = d.generate_payload(tinytuya.CONTROL, {'1': False})
d.send(payload)

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

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