-
Notifications
You must be signed in to change notification settings - Fork 172
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
Tuya Protocol 3.5 - Globe lightbulb - Unexpected payload in scan & can't control #247
Comments
Hi @Xilef11 - I may be reading this wrong since you mention sending commands (via python script), but in the example you pasted I see this...
Did you remove the Device ID from the output or was that actually blank? In any case, it is reporting that you are missing the local key. The 3.3 devices require a valid local key. If you run wizard, it will create a devices.json file that will have the local key. Run the scan again in that same directory and TinyTuya will use that local key to poll the devices. If that is not the issue, try to power cycle the device completely. I know that sounds odd, but I have seen it myself. Also, keep in mind that the local key will change if you every re-pair the device with the SmartLife app (e.g. factory reset). |
No, that's the output from the scan, all blank. devices.json was created correctly, so either it's not using the file or it can't match it to the device. I'd guess the latter since there's a
|
Edit: if anyone's just looking for an overview of the v3.5 protocol, check out #260 (comment) That's really odd. Can you post the output from: import socket
clients = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
clients.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
clients.bind(("", 6667))
clients.settimeout(7)
for i in range( 8 ):
data, addr = clients.recvfrom(4048)
print( addr, '=', data ) |
Here it is, looks like the same block repeated 8 times
I also tried a scan in debug mode, which adds the following line after the "unexpected payload=%r..." : |
o.O Well that's a new one, looks like it may be a new protocol (or at least a new encryption key). This is going to take some reverse engineering... |
I see... Anything I can do to help? |
Do you have a link to the lightbulb you bought? We're probably going to need to buy one and dump the firmware. If it's similar to one of the existing versions we might be able to figure it out with just packet captures if you're able to get them (it's not trivial to set up if you've never done it before), but if it has substantial changes then that probably won't help. |
It's this product from costco, model number on the bulb is 36819 but I can't find it on the globe website. I should be able to get you a packet capture no problem. Is there any specific part that you need? |
I basically need all the packets the phone app sends and receives to/from the bulb while in offline local-only mode, as well as the local key (you can generate a new local key if you want by removing and re-adding the bulb). I have some similar ones coming from Amazon tomorrow, no idea if they're the same or if the ones you have are Costco exclusives. I'm hoping the different part numbers are just due to the different packaging (4-pack vs 2-pack vs single). |
Getting the capture in offline mode was a bit trickier than I expected, but I think I managed to get something. Here's what I did:
Interestingly, I didn't find a direct connection between the lightbulb and the phone when the internet was offline. Just UDP broadcasts and RTPS packets. Hope I did it right. |
Sure |
Well that's odd. In that packet capture there's only a normal v3.3 device with the usual 000055aa header, it should work with TinyTuya as-is. The phone does appear to be broadcasting 00006699 packets on port 7000 though. I also do not see any local-offline communication, not sure if your computer's not seeing it as it's WiFi-to-WiFi or what. |
The scan is capture is from a second bulb in the same box, I just checked and this one is picked up by If the local/offline communication is p2p and doesn't go through the "router" I won't be able to capture it with my setup. I found an older capture of the non-working bulb which also had the 000055aa UDP broadcasts, but now it's at 00006699 (port 66667) for some reason. Edit: So the non-cooperating one says its firmware is version 1.5.10 while the working one is 1.2.16. Both say they are "up to date" |
Well my bulbs came in today. The "tunable white" ones showed up with the name "34204 - V4" and firmware version 2.9.6 and use protocol v3.3. The RGB ones showed up with the name "34207" and firmware version 1.3.21 and use protocol v3.4. @Xilef11 I would like to purchase the 00006699 bulbs you have if you don't mind selling them. |
I ended up picking up some single-pack 34212 RGB+white bulbs, and they're both version 2.9.6. I think this company's nuts for having a completely different part for a 2-pack vs single vs 4-pack, but whatever. I managed to decode the 6699 broadcast messages, though I won't be able to verify sending commands without a packet capture. from Crypto.Cipher import AES
from hashlib import md5,sha256
import socket
clients = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
clients.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
clients.bind(("", 6667))
clients.settimeout(7)
amode = AES.MODE_GCM
key = md5( b'yGAdlopoPVldABfn' ).digest()
for i in range( 8 ):
data, addr = clients.recvfrom(4048)
header = data[:18]
iv = data[18:30]
payload = data[30:-4]
print( addr, '=', payload )
decrypted = AES.new(key, amode, nonce=iv).decrypt( payload )
print( decrypted )
print('') Once decrypted these new devices are reporting protocol v3.5. |
Apologies for the delay. Unfortunately I won't be able to sell you the device, but the above code does give some legible information:
|
It's fine, no worries. At this point there's not much I can do without either a firmware dump or a packet capture of a local-offline transaction. I have the gateway from #248 coming, but it's been out for a few years now and I'm doubtful it'll arrive with the correct firmware version. You can try running this while changing something in the app, but it probably won't work: import socket
import time
ip = '192.168.2.46'
for i in range( 3 ):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout( 5 )
sock.connect( (ip, 6668) )
print( 'connected!' )
stime = time.time()
sock.settimeout( 300 )
while True:
try:
rtime = time.time()
data = sock.recv( 4096 )
except:
print( 'connection closed after ', (time.time() - stime) )
break
print( 'data:', data, 'in', (time.time() - rtime) )
if not data:
break
sock.close()
sock = None |
Yeah, it just prints empty data:
|
I recently bought a smart light imported and rebranded from a brazilian company with the same issue. Unfortunately as soon as I connected to Smart Life it's firmware got updated to version 1.5.10 Although the firmware number is lower than my other smart lights (2.9.16), on Smart Life I noticed this one has more features: Even on device list, it has a quick access toolbar unlike the others: My devices.json:
The error messages from TinyTuya are exactly the same and wireshark results are probably similar. |
Can @Xilef11 or @Oglaf run this and let me know if it reports anything? Make sure to fill in your IP and local key. import socket
import time
import struct
from hashlib import md5,sha256
from Crypto.Cipher import AES
ip = '192.168..'
key = b'YOUR LOCAL KEY'
for i in range( 2 ):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout( 5 )
sock.connect( (ip, 6668) )
print( 'connected!' )
stime = time.time()
local_nonce = b'0123456789abcdef' # not-so-random random key
local_iv = local_nonce[:12] # not-so-random random iv
pkt = struct.pack( ">IHIII", 0x6699, 0, 1, 3, len(local_nonce)+len(local_iv)+16 )
c = AES.new(key, AES.MODE_GCM, nonce=local_iv)
c.update( pkt[4:] )
encrypted, tag = c.encrypt_and_digest( local_nonce )
pkt += local_iv + encrypted + tag + struct.pack( ">I", 0x9966 )
#print( pkt )
#print( pkt.hex() )
sock.sendall( pkt )
try:
data = sock.recv( 4096 )
except:
data = None
print( 'data:', data, 'in', (time.time() - stime) )
sock.close()
sock = None |
Nop, nothing... I confirmed the code works with my other lightbulbs . Results:
|
🤦 It would help if I get the format right. Replace |
That actually works! I think. At least there's some data, not sure if it's meaningful
|
Great, that's exactly what I need! I'm almost done adding these encryption routines and should have a PR for people to test in a bit. |
FYI, got positive results:
Thank you for your help @uzlonewolf ! |
Can everyone checkout #256 (aka https://github.com/uzlonewolf/tinytuya/tree/pv35 ) and let me know if it works? |
Thank you @Xilef11 ! Good news on the status() results! That means there is still a bug in scanner.py. Can you also try this? python3 -m tinytuya scan
python3 -m tinytuya snapshot I'm more interested in the snapshot output to see if it reads the 3.5 device there. |
scan:
snapshot:
"invalid argument" from Windows when polling from the snapshot. |
@jasonacox Looks like there are 3 places in the scanner with |
Found them @uzlonewolf - Thanks! @Xilef11 can you pull the latest and try the scan again? |
I'm also working on the snapshot issue, hopefully I'll have a PR for that one soon |
@jasonacox and @uzlonewolf do you guys still needs me to send any log? |
new error! here's the scan
This is on commit |
Lovely. I'll get that fixed. |
Scan results:
Snapshot:
Script: import tinytuya
d = tinytuya.OutletDevice('eb68e355da1be4ae69ok5o', '192.168.1.205', '6434389541e96704')
d.set_version(3.5)
d.set_socketPersistent(True)
print(d.status()) Result: Edit: Corrected status result. |
Thanks @Oglaf - That's great news on the status() success! 🎉 Thanks for your help. @uzlonewolf is looking at the scanner issues. |
Well that PR does give correct output on |
That's great news! Thanks for helping test. The changes from @uzlonewolf have been merged into the main repo. A huge thanks to @uzlonewolf ! 🙇 You are brilliant! Please report any other issues. I'll continue my standard battery of test (even though I don't have a 3.5 device) and if all goes well, will be releasing tinytuya v1.10.0 to PyPI later tonight. |
New release published https://pypi.org/project/tinytuya/1.10.0/ pip install --upgrade tinytuya |
@uzlonewolf I also stumbled over that. One question: Is just the "discovery" message is in the new format or also all local messages? |
@Apollon77 All messages, both discovery and local. |
Thank you ... yeeaaayyy ... more work :-) ... They should concentrate on Matter (like me) and not to invent new tuya protocols ;-) |
Added a "Device discovery broadcast packets" section to my Protocol Notes #260 |
Thank you! |
If anyone wants v3.5 devices, the bulbs I got from https://www.ebay.com/itm/395006526624 came with v3.5 (firmware is reporting V1.5.21). |
Thanks! Ordered. |
Got this today. You are right, finally have my first legit v3.5 device. 😂 SmartBulb Product ID = key8u54q9dtru5jw [Valid Broadcast]: |
@uzlonewolf Can you please provide a simple decrypt packet test for 3.5 as you did for this request. I'm wanting to try and update tuyapi for 3.5. I have the request working but I can't get the decrypt to work. Thanks!
|
Hi,
I have an RGB lightbulb that I'm trying to control, and although the wizard managed to pull the device information and local key from the cloud, I can't control the device. The scan finds it, but gets an "unexpected payload":
When trying to send commands, I get
{'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}
. I tried all protocol versions and the "device22" device type, to no avail. Enabling debug mode only reveals a "timeout in_send_receive()
" and no reply from the bulb. Control usingtinytuya.Cloud
works perfectly. I can ping the bulb's IP with no problem.I checked the datapoint codes on the website and they seem to match the "version 3.3 - light type (RGB)" table in the README. However, trying to set these values through code doesn't work.
Any ideas?
Thanks!
The text was updated successfully, but these errors were encountered: