Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCP packet not decoded #505

Open
leweafan opened this issue Jun 4, 2024 · 11 comments
Open

TCP packet not decoded #505

leweafan opened this issue Jun 4, 2024 · 11 comments

Comments

@leweafan
Copy link

leweafan commented Jun 4, 2024

Hi all,
I'm trying to figure out why tinytuay can't get my device status and localtuya can.
I see that tinytuya decodes only UDP packets and ignores TCP packet and in case of localtuya TCP packet decoded.
DP_QUERY makes the same request as localtuya does but also ignores TCP packet.

Can you help me to understand why I can't get my device status from TCP packet. May be I'm missing some config parameter.

Using tinytuya I get the following output.

python3 -m tinytuya snapshot -debug
/Library/Python/3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(
Parsed args: Namespace(debug=False, command='snapshot', debug2=True, nocolor=False, yes=False, no_poll=False, device_file='devices.json', snapshot_file='snapshot.json')
DEBUG:TinyTuya [1.14.0]

DEBUG:Python 3.9.6 (default, May  7 2023, 23:32:44) 
[Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
DEBUG:Using pyca/cryptography 42.0.7 for crypto, GCM is supported

TinyTuya (Tuya device scanner) [1.14.0]

Loaded snapshot.json - 1 devices:

Name                      ID                       IP              Key               Version

bfc6d450d7e2a0b4322mkq    bfc6d450d7e2a0b4322mkq   192.168.1.129   xxx               3.3  

Poll local devices? (Y/n): 

Polling 1 local devices from last snapshot...
DEBUG:Listening for Tuya devices on UDP ports 6666, 6667 and 7000
DEBUG:Starting brute force network scan 192.168.1.129/32
DEBUG:final payload_dict for 'bfc6d450d7e2a0b4322mkq' ('v3.3'/'default'): {1: {'command': {'gwId': '', 'devId': '', 'uid': '', 't': ''}}, 7: {'command': {'devId': '', 'uid': '', 't': ''}}, 8: {'command': {'gwId': '', 'devId': ''}}, 9: {'command': {'gwId': '', 'devId': ''}}, 10: {'command': {'gwId': '', 'devId': '', 'uid': '', 't': ''}}, 13: {'command': {'devId': '', 'uid': '', 't': ''}}, 16: {'command': {'devId': '', 'uid': '', 't': ''}}, 18: {'command': {'dpId': [18, 19, 20]}}, 64: {'command': {'reqType': '', 'data': {}}}}
DEBUG:building command 10 payload=b'{"gwId":"bfc6d450d7e2a0b4322mkq","devId":"bfc6d450d7e2a0b4322mkq","uid":"bfc6d450d7e2a0b4322mkq","t":"1717532171"}'
DEBUG:payload encrypted=b'000055aa000000010000000a00000088dc40fff63637ebe1bb53989b3b59f8bc290478a70639e4612f8e03ca9828291671d4a5cb65c969d1e392e89f3350fb852bdf55fc1ce2e32cb823afd939ca7ae1a64fe2bafce8105731d5d7cae0d3d0db290478a70639e4612f8e03ca982829166311eaa071ee1f5707787a4a36fdffc10d2128a1c02b2b2ed26bf4435d68ff6cedfcd0bf0000aa55'
DEBUG:PollDevice: raw unpacked message = TuyaMessage(seqno=0, cmd=8, retcode=0, payload=b'3.3\x00\x00\x00\x00\x00\x01\x81\xf0\x00\x00\x00\x01U\xe1\xe1\x18+\x0e\x89\xaf[2\xackG^\x9e\xc0w\xf4\x10\x85\xde\x80#\xbfN\xd8\xfb.\xd8\xab\xd5r\xfb\x9et\xeb"\xe3\xe5\x0f>0\x89\x95\x9c-\x1d9', crc=975962185, crc_good=True, prefix=21930, iv=None)
DEBUG:decode payload=b'3.3\x00\x00\x00\x00\x00\x01\x81\xf0\x00\x00\x00\x01U\xe1\xe1\x18+\x0e\x89\xaf[2\xackG^\x9e\xc0w\xf4\x10\x85\xde\x80#\xbfN\xd8\xfb.\xd8\xab\xd5r\xfb\x9et\xeb"\xe3\xe5\x0f>0\x89\x95\x9c-\x1d9'
DEBUG:removing 3.x=b'U\xe1\xe1\x18+\x0e\x89\xaf[2\xackG^\x9e\xc0w\xf4\x10\x85\xde\x80#\xbfN\xd8\xfb.\xd8\xab\xd5r\xfb\x9et\xeb"\xe3\xe5\x0f>0\x89\x95\x9c-\x1d9'
DEBUG:decrypting=b'U\xe1\xe1\x18+\x0e\x89\xaf[2\xackG^\x9e\xc0w\xf4\x10\x85\xde\x80#\xbfN\xd8\xfb.\xd8\xab\xd5r\xfb\x9et\xeb"\xe3\xe5\x0f>0\x89\x95\x9c-\x1d9'
DEBUG:decrypted 3.x payload='{"dps":{"114":"AwMDAw=="},"t":1717532170}'
DEBUG:payload type = <class 'str'>
DEBUG:decoded results='{"dps":{"114":"AwMDAw=="},"t":1717532170}'
DEBUG:Scan complete with 1 devices found
    [bfc6d450d7e2a0b4322mkq   ] 192.168.1.129      - DPS: {'114': 'AwMDAw=='}

As you can see from debug only UDP ports listned:
DEBUG:Listening for Tuya devices on UDP ports 6666, 6667 and 7000

Using localtuya I get the following output where all DPS are presented:

2024-06-04 19:06:35.347 DEBUG (MainThread) [custom_components.localtuya.pytuya] [bfc...mkq] Sending command 10 (device type: type_0a)
2024-06-04 19:06:35.347 DEBUG (MainThread) [custom_components.localtuya.pytuya] [bfc...mkq] Sending payload: b'{"gwId":"bfc6d450d7e2a0b4322mkq","devId":"bfc6d450d7e2a0b4322mkq","uid":"bfc6d450d7e2a0b4322mkq","t":"1717517195"}'
2024-06-04 19:06:35.358 DEBUG (MainThread) [custom_components.localtuya.pytuya] [bfc...mkq] Command 10 waiting for seq. number 1
2024-06-04 19:06:35.378 DEBUG (MainThread) [custom_components.localtuya.pytuya] [bfc...mkq] Dispatching message CMD 10 TuyaMessage(seqno=1, cmd=10, retcode=0, payload=b'\xbc\x14\xb8\x03\xee/\x80\x0c\xf7\x1c\xae\x1d\x8f\xe4"0\x9f#\xa2\xf7\xad\xb0S\x03\xed\xab\x8d`8\xab\x1dM\x81\xa8\xf2\x08\xc3\xc8^\xcc\xae\xf0\x98\xa1>\x9d\xaawI\x82\xdcvn.J!\x8d\xf0\xbf\x0e\xa6Y\x93I\xc7\xa8\x1f\xd0\x92]\x1d\xe8\xae\r\xafP\x84[D\xe8\xb7\xa2Z\xc9\xc3\xc9\x85l\xba\xa2\xde\xbd\xf5\xe99\xaa\x93\x04\xa24\xd2Z\x0b\x10\xaa\x06\xd5H\xe5\xb7\xadL=\x87nwj\x9bm\xbd\x16H\x99(^\x87\xac\x00-I\xf7\x8e\xc6\xb1\xb2\xbd\xce\xcejg\xf1\x8e\xa0\xa8C\xc5\xca\xa0\xbd4\xb8w\xec&\x87\r\xa3@\x91S\xfdI\xa5\xa2\xecNi\xf5\xf7\x02WS\xf9\xae\x8e\xe3\x0e\xbc\xd5\x86uR\xda\x93|=+\'\x17*\xa8\xab\xc1\xf9\xddo\\\x86\x90\xbdO\xee\x9e\xbb<\xd2\x02\xb3\xe1<3}\x1b\xccq\xd2\x8eM=n\xe9\x06\xae\xa1(m\x19\xbcV+\x96.m\x8e\xfa\x8ahx\x89\xfe\xd7n\xad\x0e\x10\xa5\x11\x01\x93\xbf\xa4\xc8\n\xe0s\x87\xf5\xf6rk\x90\x19\x86\x85\xcf\xa3\xb4\xcd\x9f\xd5+eY\x1d\xe4\xacS^\xdb]\xb3p\xb9\xa8\x9f\x8d\x00\x8b6\xf6\xecQ/\xd8So\x97\x8d\x88\xc9;A\xaaGHd[gs8\x94\xb4*\xfd\x7f\xb5\xbd\xf5\xd3\n\x85s4B\xaf\xbeQ\xd9\x92ASp\x90\x8b\x14\xab\x83\xa9\xe1\xa9f#\xb5&\xec\xd8\x8f\xb8&\x83\x97\xe5D\xc6Z\xca\xc9@M{\x0c#\x80^\xe8 \xc5\xd2+{c\xb0\x01\n\xde\xd9P\x92\t. X\x80\x9b\xa6\xc9\xafc\x89\x156\xfb\x13\x11\\}\x17C5x\xa9w\xa6\xf5\x03?\xa7\x9fjB\x1d\xa5\xf4X\x12\xb0B\xdb\xc4\xa1\x80\xcf\x00>.\xa49p\xcd\r\x14\xd5\x14(\xef\x9a\t\xcb#\xa6\x16\xdeEC\x04\x83\xbe\xf8\xb9p\xdci\x06a\x9c\xf7\x88\xa9\xb9;h#O\xd0G\x8be-\x8cI1\xb2n\xe5\xe0\xc1\xa6\xd68"\x16C\xca\x08\x9ffsA\xe0\xcc\xb46sM\xcdw\x9b\xc1\xa7}1\xcf\xea\xa0N\xd6\xb9P\xe6q\xd3\x0e(!\x91\x8b\x14Q"I%F\x12\x90\x15\x9f\xd7hK\x93\xbb\xeb.T\xbdn\xba\x98\xe2h\x95\xb0\x02\x8f\x99Q\x96\x95\xc1\xf4\xcb\xac(\xaf\xc3\t\x92\r\x83\xc8\x12D|q\x92\xc0\xf4~\x85\xb4^\xb8\x93@S\x17\xae\x87\xd8U\xf0\xfb\\\x9bf\xa8\xdb\x11Ld\x14\xc1\xbb\xf4\xa6/(\x9b\xcf\xf3m4\x14\x9aM\xe7\xb9\xc5\x02\x02\xfb\x19\xaa?Oo\xf6J\xf0\xbc8\xa4\xf4\xd7\xcf|\x81\x1c\xbc\x93\x9f\x00m=\x1e*}\xe8n\xf5?\xebIN\'\xaeH\x05&!V\xd4X\xf9\xb8\x81\xd9\xcf\xd4\x87\xb6\xef\xc3\\\xec\xe6L\x12\xf4\xb2\xd4\xb1\xe6YT\x82\xd7\'\xa4\xd3S!\xf7\xdc%8\xc2_]u\xf45\x080)\xe1\xfe\xdc-\x96{\x04\xaaU\xcb\x853\x9b*1\xe8>\xe2O\xc5\xa4\xd1N)\xe1\nh}\xa8\xc53\xa4q\xcd\x99\xc8\xaf\xee\xa6\xda/%r\xa1\xcb\xa2\x02\x10&\x8a8P\xf2\xc2\x8f\xfa]g\xbc\x12=\x00m@b%\xdfqv\xac5\x7fW\xdb\xa6HiwT/\x07\xd7\x1b\xcd/5\xf9mc,=\x01\xa1h!\x97\xf9\x1e\'\x06\x12\xcb\xe1w\x18e\xbb\xfe\x8f\xbb\x00Q\xa9[`\x8cf\x9c/I0\x16km\xd4E\xf9\xcd\xa6\xda\xcd\x83j\x91\x86&\x04\x8by\x8d\xf4\x8f_u\x01k\xfbP\xf9\xff\xe0\xbd,\x90\x90\xab\xc9\x18\r\xe7\x19\xea\xf3\xd14\xf3|\x82\x14[\xdd\xaa\x82\xc1\xae\xab\x10y\xa7|\x84x\xddhe1^u\xd6(L$*\x82\x9c\xf9\xd8\x0b)C\xa4\xa9\xd7L\xd8\xa2\x96\xc2i\xed\x0c\xcfR\xf7\xff\xa5\t\xc1\x16\xe4\x07\x11TG_e8\x19m\x1b,\xb7|\x94Z\x12M\xf2\x9b(B7Gf\x80\xd9\xf5\xfa`HJI\xf6s\xda\xed\xa9v*1p\xab\x00\xeamR2\x00\xb4/}\xafE\xd6g\xd6[bv\xa4\xd6+\xc9\xa8N\x9bk\x14w\xb3\x8df\xc0i\xe5g\xa6h\xce:\xb7\x11\x81\xc8"\xfcU\xa4\xb1\xf4r\xbd\x8f\x82s\xe4\t!\x9f\x93\xed\xae\xb6\xd1\xb5\xf6\xbe=`\x1f\xf2l\xe4~\xb8\x16\xbf4\xf7\xf3H\xa8\xf56;\xed]\x19\x86`p6\xb4\x1e\xc1?\x9a\xe1\xd1\xf7:\xc0\xd4dq\x18 \x8c\x8e\x19\x1a\x8a\x1e\x1c\xd0\xd6\x0b\x89G;_\xdc\xba\x8eZ\xc1\xbf\x9e_\x9d\xa0\x1b=\xe4\xf6XM\x19\x1e\xbf\xfe\xd2^\xd0\x9f\xads\xbf\xfd', crc=3218256607, crc_good=True)
2024-06-04 19:06:35.382 DEBUG (MainThread) [custom_components.localtuya.pytuya] [bfc...mkq] Deciphered data = '{"dps":{"101":false,"108":false,"109":true,"110":true,"111":false,"112":false,"113":false,"115":0,"116":3,"117":240,"118":"9600","119":0,"123":0,"124":"RF Sensor  1,RF Sensor  2,RF Sensor  3,RF Sensor  4,RF Sensor  5,","125":"RF Sensor  6,RF Sensor  7,RF Sensor  8,RF Sensor  9,RF Sensor 10,","126":"RF Sensor 11,RF Sensor 12,RF Sensor 13,RF Sensor 14,RF Sensor 15,","127":"RF Sensor 16,RF Sensor 17,RF Sensor 18,RF Sensor 19,RF Sensor 20,","128":"RF Sensor 21,RF Sensor 22,RF Sensor 23,RF Sensor 24,RF Sensor 25,","129":"RF Sensor 26,RF Sensor 27,RF Sensor 28,RF Sensor 29,RF Sensor 30,","130":"RF Sensor 31,RF Sensor 32,RF Sensor 33,RF Sensor 34,RF Sensor 35,","131":"RF Sensor 36,RF Sensor 37,RF Sensor 38,RF Sensor 39,RF Sensor 40,","132":"RF Sensor 41,RF Sensor 42,RF Sensor 43,RF Sensor 44,RF Sensor 45,","133":"RF Sensor 46,RF Sensor 47,RF Sensor 48,RF Sensor 49,RF Sensor 50,","134":"Line 1,Line 2,Line 3,Line 4","135":"Zone 1,Zone 2","136":"Counter 1,Counter 2,Counter 3,Counter 4,Counter 5,Counter 6,Counter 7,Counter 8,","137":0,"138":0,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0}}'

TCPDUMP flow:

22:46:47.159279 IP 192.168.1.129.49155 > broadcasthost.6667: UDP, length 172
22:46:51.408624 IP 192.168.1.83.54312 > 192.168.1.129.6668: Flags [S], seq 2711958239, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 3372608596 ecr 0,sackOK,eol], length 0
22:46:51.495773 IP 192.168.1.129.6668 > 192.168.1.83.54312: Flags [S.], seq 55448216, ack 2711958240, win 2920, options [mss 1460], length 0
22:46:51.495945 IP 192.168.1.83.54312 > 192.168.1.129.6668: Flags [.], ack 1, win 65535, length 0
22:46:51.524135 IP 192.168.1.83.54312 > 192.168.1.129.6668: Flags [P.], seq 1:153, ack 1, win 65535, length 152
22:46:51.541550 IP 192.168.1.129.6668 > 192.168.1.83.54312: Flags [P.], seq 1:1133, ack 153, win 2768, length 1132
22:46:51.541682 IP 192.168.1.83.54312 > 192.168.1.129.6668: Flags [.], ack 1133, win 65535, length 0
22:46:52.106741 IP 192.168.1.129.49155 > broadcasthost.6667: UDP, length 172
22:46:55.799895 IP 192.168.1.129.6668 > 192.168.1.83.54312: Flags [P.], seq 1133:1224, ack 153, win 2768, length 91
22:46:55.800044 IP 192.168.1.83.54312 > 192.168.1.129.6668: Flags [.], ack 1224, win 65535, length 0
22:46:55.812233 IP 192.168.1.83.54312 > 192.168.1.129.6668: Flags [F.], seq 153, ack 1224, win 65535, length 0
22:46:55.820266 IP 192.168.1.129.6668 > 192.168.1.83.54312: Flags [.], ack 154, win 2767, length 0
22:46:55.829875 IP 192.168.1.129.6668 > 192.168.1.83.54312: Flags [R.], seq 1224, ack 154, win 2920, length 0

The TCP packet I've mentioned:
22:46:51.541550 IP 192.168.1.129.6668 > 192.168.1.83.54312: Flags [P.], seq 1:1133, ack 153, win 2768, length 1132

@jasonacox
Copy link
Owner

Hi @leweafan ,

Thanks for opening this. Wow, that is a big payload!

only UDP ports are listened

That's correct, but only for discovery. Tuya devices announce themselves on the network via UDP broadcasts. TinyTuya listens to those to discover devices. But that isn't related to the issue you are seeing. The debug you have shows TCP traffic which is how TinyTuya and localtuya both communicate with Tuya devices.

I notice that in your example, TinyTuya gets a response packet with just one DPS (114) however, localtuya gets a response with everything BUT 114. That means that the device seems to be sending back two different payloads. You will likely need to keep monitoring to get all the DPS payloads (or query it multiple times).

You can try this script which will keep monitoring the device and print everything that comes back from it:

import tinytuya
import time
# tinytuya.set_debug(True)
# Setting the address to 'Auto' or None will trigger a scan which will auto-detect both the address and version, but this can take up to 8 seconds
d = tinytuya.OutletDevice('DEVICEID', 'Auto', 'DEVICEKEY', persist=True)
# If you know both the address and version then supplying them is a lot quicker
# d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY', version=DEVICEVERSION, persist=True)
STATUS_TIMER = 30
KEEPALIVE_TIMER = 12
print(" > Send Request for Status < ")
data = d.status()
print('Initial Status: %r' % data)
if data and 'Err' in data:
print("Status request returned an error, is version %r and local key %r correct?" % (d.version, d.local_key))
print(" > Begin Monitor Loop <")
heartbeat_time = time.time() + KEEPALIVE_TIMER
status_time = None
# Uncomment if you want the monitor to constantly request status - otherwise you
# will only get updates when state changes
#status_time = time.time() + STATUS_TIMER
while(True):
if status_time and time.time() >= status_time:
# Uncomment if your device provides power monitoring data but it is not updating
# Some devices require a UPDATEDPS command to force measurements of power.
# print(" > Send DPS Update Request < ")
# Most devices send power data on DPS indexes 18, 19 and 20
# d.updatedps(['18','19','20'], nowait=True)
# Some Tuya devices will not accept the DPS index values for UPDATEDPS - try:
# payload = d.generate_payload(tinytuya.UPDATEDPS)
# d.send(payload)
# poll for status
print(" > Send Request for Status < ")
data = d.status()
status_time = time.time() + STATUS_TIMER
heartbeat_time = time.time() + KEEPALIVE_TIMER
elif time.time() >= heartbeat_time:
# send a keep-alive
data = d.heartbeat(nowait=False)
heartbeat_time = time.time() + KEEPALIVE_TIMER
else:
# no need to send anything, just listen for an asynchronous update
data = d.receive()
print('Received Payload: %r' % data)
if data and 'Err' in data:
print("Received error!")
# rate limit retries so we don't hammer the device
time.sleep(5)

@leweafan
Copy link
Author

leweafan commented Jun 5, 2024

Hello @jasonacox!

Actually I have tried it cause seen in other issues.

All I can catch using this script is DPS of counters (137-144).

 > Begin Monitor Loop <
Received Payload: {'dps': {'122': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='}, 't': 1717564981}
Received Payload: {'dps': {'137': 0}, 't': 1717564981}
Received Payload: {'dps': {'138': 0}, 't': 1717564981}
Received Payload: {'dps': {'139': 0}, 't': 1717564981}
Received Payload: {'dps': {'140': 0}, 't': 1717564981}
Received Payload: {'dps': {'141': 0}, 't': 1717564981}
Received Payload: {'dps': {'142': 0}, 't': 1717564981}
Received Payload: {'dps': {'143': 0}, 't': 1717564981}
Received Payload: {'dps': {'144': 0}, 't': 1717564981}
Received Payload: {'dps': {'145': 'Bf///w=='}, 't': 1717564981}
Received Payload: None
Received Payload: None
Received Payload: {'dps': {'114': 'AwMDAw=='}, 't': 1717564996}
Received Payload: {'dps': {'122': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='}, 't': 1717564996}
Received Payload: {'dps': {'137': 0}, 't': 1717564996}
Received Payload: {'dps': {'138': 0}, 't': 1717564996}
Received Payload: {'dps': {'139': 0}, 't': 1717564996}
Received Payload: {'dps': {'140': 0}, 't': 1717564996}
Received Payload: {'dps': {'141': 0}, 't': 1717564996}
Received Payload: {'dps': {'142': 0}, 't': 1717564996}
Received Payload: {'dps': {'143': 0}, 't': 1717564996}
Received Payload: {'dps': {'144': 0}, 't': 1717564996}
Received Payload: {'dps': {'145': 'Bf///w=='}, 't': 1717564996}
Received Payload: None
Received Payload: None
...

I've also used tinytuya wizard and got only DP 114.

Can I get data from TCP packet using tinytuya?

@jasonacox
Copy link
Owner

Can I get data from TCP packet using tinytuya?

I'm not following what you mean. These are all TCP packets. Do you mean running a packet capture?

What is this device and can you send a link to it? I may have to try to buy one to help you debug.

I suspect it has something to do with the seqno (sequence number). It looks like Tinytuya is only picking up seqno = 0 and localtuya is only picking up seqno = 1 and avoiding seqno = 0. Do you know the function/meaning of DPS 114?

@leweafan
Copy link
Author

leweafan commented Jun 5, 2024

I'm not following what you mean. These are all TCP packets. Do you mean running a packet capture?

Yes I would like to get device DPs (reads state) and seems its all in TCP packet only.

What is this device and can you send a link to it? I may have to try to buy one to help you debug.

I suppose it's not available worldwide. It's tuya code "sfkzq" - "Water valve controller". It supports 50+ wireless sensors that's is why TCP packet so big IMHO.

I suspect it has something to do with the seqno (sequence number). It looks like Tinytuya is only picking up seqno = 0 and localtuya is only picking up seqno = 1 and avoiding seqno = 0.

Do you know where I can read more about Tuya API sequence number?

Do you know the function/meaning of DPS 114?

{
   "abilityId":114,
   "accessMode":"rw",
   "code":"line_settings",
   "description":"Settings for four lines.\n{input_type_1, control_group_1 },\n{input_type_2, control_group_2 },\n{input_type_3, control_group_3 },\n{input_type_4, control_group_4 }\n\ninput_type - byte, ref. as (0-sensor/1-key)\ncontrol_group - byte, ref. as (1-control group 1; 2-control group 2; 3-control both group)\n",
   "name":"Line settings",
   "typeSpec":{
      "type":"raw",
      "maxlen":128
   }
}

I have created device config using localtuya and want to share it with community but seems that localtuya do not use yaml configs anymore and switched to config flow (UI) as I understood. That's why I decided to create config for tuya-local project but seems that it's using tinytuya and can't discover and manage my device.

@uzlonewolf
Copy link
Collaborator

uzlonewolf commented Jun 5, 2024

Try this modified version of the above script (don't forget to replace DEVICEKEY with your key):

key = 'DEVICEKEY'

######### Don't change anything below here ##########

import tinytuya
import time

d = tinytuya.Device('bfc6d450d7e2a0b4322mkq', '192.168.1.129', key, version=3.3, persist=True)

STATUS_TIMER = 3
status_time = time.time() + STATUS_TIMER - 2

print(" > Begin Monitor Loop <")

while(True):
    if status_time and time.time() >= status_time:
        # poll for status
        print(" > Send Request for Status < ")
        data = d.status()
        status_time = time.time() + STATUS_TIMER
    else:
        # no need to send anything, just listen for an asynchronous update
        data = d.receive()

    print('Received Payload: %r' % data)

    if data and 'Err' in data:
        print("Received error!")
        # rate limit retries so we don't hammer the device
        time.sleep(5)

@leweafan
Copy link
Author

leweafan commented Jun 5, 2024

Nothing changed only counters broadcasted all other DP should be polled.

 > Begin Monitor Loop <
Received Payload: {'dps': {'114': 'AwMDAw=='}, 't': 1717624282}
 > Send Request for Status < 
Received Payload: {'dps': {'122': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='}, 't': 1717624283}
Received Payload: {'dps': {'137': 0}, 't': 1717624283}
Received Payload: {'dps': {'138': 0}, 't': 1717624283}
Received Payload: {'dps': {'139': 0}, 't': 1717624283}
Received Payload: {'dps': {'140': 0}, 't': 1717624283}
Received Payload: {'dps': {'141': 0}, 't': 1717624283}
Received Payload: {'dps': {'142': 0}, 't': 1717624283}
Received Payload: {'dps': {'143': 0}, 't': 1717624283}
Received Payload: {'dps': {'144': 0}, 't': 1717624283}
Received Payload: {'dps': {'145': 'Bf///w=='}, 't': 1717624283}
Received Payload: None
 > Send Request for Status < 
Received Payload: {'dps': {'114': 'AwMDAw=='}, 't': 1717624297}
Received Payload: {'dps': {'122': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='}, 't': 1717624298}
Received Payload: {'dps': {'137': 0}, 't': 1717624298}
Received Payload: {'dps': {'138': 0}, 't': 1717624298}
Received Payload: {'dps': {'139': 0}, 't': 1717624298}
Received Payload: {'dps': {'140': 0}, 't': 1717624298}
Received Payload: {'dps': {'141': 0}, 't': 1717624298}
Received Payload: {'dps': {'142': 0}, 't': 1717624298}
Received Payload: {'dps': {'143': 0}, 't': 1717624298}
Received Payload: {'dps': {'144': 0}, 't': 1717624298}
Received Payload: {'dps': {'145': 'Bf///w=='}, 't': 1717624298}
Received Payload: None 
...

I think you are right and localtuya does the trick using seqno=1 to get all DPS from device.

P.S. Added KEEPALIVE_TIMER = 12

Thanks for your time @jasonacox

@jasonacox
Copy link
Owner

I need to do more investigation on this. Thanks for raising it @leweafan

@jasonacox
Copy link
Owner

Hi @leweafan I have something for you to test. I have released a dev version that simply ignores seqno=0.

pip install tinytuya==1.14.1.dev0

You can use the python -m tinytuya scan and also try to poll your one device with a simple:

import tinytuya

key = 'DEVICEKEY'
d = tinytuya.Device('bfc6d450d7e2a0b4322mkq', '192.168.1.129', key, version=3.3)
print(d.status())

jasonacox added a commit that referenced this issue Jun 11, 2024
@uzlonewolf
Copy link
Collaborator

You can give it a shot, but I find it highly unlikely to help; a non-zero sequence number would have been picked up in the modified monitor script I posted above.

@leweafan
Copy link
Author

Hello @jasonacox!

Sorry for delay. I have tested a new version and got nothing. Scan is working fine but the new script and old ones don't work. Made rollback to the previous version.

@jasonacox
Copy link
Owner

Thanks @leweafan - As @uzlonewolf predicted, no difference. Thanks for trying. Without the device, I'm not sure what more we can try. Sorry about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants