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

General Discussion #5

Open
jepsonrob opened this issue Nov 28, 2017 · 433 comments
Open

General Discussion #5

jepsonrob opened this issue Nov 28, 2017 · 433 comments
Labels

Comments

@jepsonrob
Copy link
Contributor

@jepsonrob jepsonrob commented Nov 28, 2017

I'm trying to get this to work with some smart bulbs and light strip, but currently the only missing piece for me is how you got the prefix & suffix in requests.json.
Are they just the packet header/footer or is there more to it than that?

Awesome work here by the way, thanks for all your work!

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Nov 28, 2017

Yep. To find the prefix and suffix for new devices, you'll have to fire up Wireshark and sniff the packets going to your device. The data portion of the packet starts with a version number (probably 3.1) and ends with = or == (a base 64 encoded string). The rest of the packet before and after (not including other TCP segments, like destination IP, checksum, etc.) that data string is what's plugged into the prefixes and suffixes.

I'm guessing this padding has an actual meaning, but so far I haven't been able to find anything. @blackrozes has suggested that it's just random data with a few special bytes in the beginning and end as devices seem to expect a fixed packet length. If you have any theories, I'd love to hear them.

@jepsonrob
Copy link
Contributor Author

@jepsonrob jepsonrob commented Nov 28, 2017

Yeah I've just checked in Wireshark and it fits your description perfectly.

Are you sure everything before the 00 00 55 aa part of the prefix is necessary to use with on & off? It appears be the TCP information you were talking about, and you cold be hardcoding your own private IP addresses into it (looks like your outlet is on 192.168.0.108).

As to theories, I'm noticing that the 8th hex value (starting from 00 00 55 aa) increments by 1 with every request and everything else but the very last bit is identical across the board, including in my own packets. The last bit before the data appears to only be either b3, 9b, 46 or 00 in both my own and your prefixes. Not sure what these represent at all!

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Nov 29, 2017

Oh wow thanks. I was going to say "sorry for the confusion, I meant that you shouldn't include the TCP packet metadata", but then I looked at requests.json 🙄. Oops. I'll push an update in a few minutes removing the hex metadata.

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Nov 29, 2017

Updated with b766439. I've now whittled them down to this:

"outlet": {
    "status": {
      "prefix": "000055aa000000000000000a00000046",
      "command": {"gwId": "", "devId": ""},
      "suffix": "000000000000aa55"
    },
    "on": {
      "prefix": "000055aa00000000000000070000009b",
      "command": {"devId": "", "dps": {"1": true}, "uid": "", "t": ""},
      "suffix": "000000000000aa55"
    },
    "off": {
      "prefix": "000055aa0000000000000007000000b3",
      "command": {"devId": "", "dps": {"1": false}, "uid": "", "t": ""},
      "suffix": "000000000000aa55"
    }
  }

I tried tearing out the ...7... and ...a..., replacing them with 0s, but it didn't work. So they must mean something. Same with 46, 9b, b3.

Is it working with your device yet?

@blackrozes
Copy link

@blackrozes blackrozes commented Nov 29, 2017

I think the devices are expecting a special packet size. In my script I create a buffer with this size and put the data inside like this:

var buf1 = new Buffer(171); 
buf1.write('000055aa00000000000000070000009b'+ (data),0,"hex");
buf1.write('0000aa55',167,"hex");
@jepsonrob jepsonrob changed the title How to get the prefix and suffix from requests.json Understanding the packet hex-encoded padding Nov 29, 2017
@jepsonrob
Copy link
Contributor Author

@jepsonrob jepsonrob commented Nov 30, 2017

Okay I've done some analysis of these packets and have figured some stuff out:

Prefix & Suffix
The prefix is always (from my tests) 16 bytes long.

The first half - 8 bytes 00:00:55:aa:00:00:00:6b - of our packet is static, except for the last (8th) byte. The 8th byte increments by one every time a new command is sent, but I've seen some results that add more than this using commands that were not on/off. At any rate, it is just a counter and I think it doesn't really matter what the value is.

The second half - 00:00:00:07:00:00:00:9b - gives 2 pieces of information: the type of packet being sent and the length of the remaining the data/packet. So far I've found that the 4th byte is 07 when sending commands, 08 when receiving a reply from the device, '9e' for broadcast messages, and 0a when getting the status (haven't tested the status flag but I'm assuming this is the case from your prefix in requests.json).

The final value (the 16th byte of the whole prefix) is the size in bytes of the subsequent packet (obviously as a hex value). This is the length of the encrypted data in bytes plus the suffix - basically everything after the prefix. From my tests the suffix has always been 8 bytes.

I have no idea how the suffix is created, but it doesn't seem to change anything and I've had good results leaving it as 000000000000aa55. I'm still not quite there with getting this working on these devices yet, but knowing how the prefix work feels like most of the heavy lifting.

Connections & Broadcasts

When the device is not connected, it sends out UDP broadcast packets to the network every 3-6 seconds. This contains plaintext JSON with the following information:
{"ip":"192.168.0.xx","gwId":"002003595ccfxxxxxxxx","active":2,"ability":0,"mode":0,"encrypt":true,"productKey":"AqHUMdcbxxxxxxxx","version":"3.1"}

This could be used as a way of enumerating devices on the network and all information other than the key.

Furthering the enumeration aspect, we get a plaintext list of commands available on the device from the initial connection handshake: sending the
{"gwId":"002003595ccxxxxxxx","devId":"002003595ccfxxxxxxxx"}
packet leads to a plaintext JSON status response from the device:
{"devId":"002003595ccfxxxxxxxx","dps":{"1":true,"2":"colour","3":255,"4":255,"5":"00ff0d007bffff","6":"00ff0000000000","7":"ffff500100ff00","8":"ffff8003ff000000ff000000ff000000000000000000","9":"ffff5001ff0000","10":"ffff0505ff000000ff00ffff00ff00ff0000ff000000"}}
which can in turn be used to enumerate JSON for the specific device.

One thing I've struggled with is actually decrypting the packets sent/received using the key. Has anyone got a deciphering script?

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Nov 30, 2017

@jepsonrob thanks, that's really helpful.

Receiving Broadcasted Messages

For anyone interested, you can receive the UDP broadcasted packets with a simple script:

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.log(`server error:\n${err.stack}`);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});

server.on('listening', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(6666);

I may add auto discovery functionality soon, although it's not a huge priority for me so if some else wants to do it and open a pull request I'd be very grateful.

For Decrypting:

Basically, just do the reverse of this:

  // Encrypt data
  this.cipher.start({iv: ''});
  this.cipher.update(forge.util.createBuffer(JSON.stringify(thisRequest.command), 'utf8'));
  this.cipher.finish();

  // Encode binary data to Base64
  const data = forge.util.encode64(this.cipher.output.data);

  // Create MD5 signature
  const preMd5String = 'data=' + data + '||lpv=' + this.version + '||' + this.key;
  const md5hash = forge.md.md5.create().update(preMd5String).digest().toHex();
  const md5 = md5hash.toString().toLowerCase().substr(8, 16);

  // Create byte buffer from hex data
  const thisData = Buffer.from(this.version + md5 + data);
  const buffer = Buffer.from(thisRequest.prefix + thisData.toString('hex') + thisRequest.suffix, 'hex');

I'll try to add a specific decryption function within the next couple days.

@clach04
Copy link
Contributor

@clach04 clach04 commented Dec 3, 2017

@jepsonrob when you say, " not connected, it sends out UDP broadcast". Do you mean on the network but no devices are connected to it?

I tried both @codetheweb 's suggested js listener script and a Python script based on SSDP discovery code on port 6666 and I'm not seeing anything.

BTW thanks for excellent write ups, I now have a Python version, its rough and ready but works :-) https://github.com/clach04/python-tuya

One thing I've noticed is that if there are spaces in the json payload, the device will not respond. Not an issue under js, but the Python stdlib library adds spaces.

@jepsonrob
Copy link
Contributor Author

@jepsonrob jepsonrob commented Dec 3, 2017

@clach04 - that's exactly what I mean, yep. It's potentially useful for enumeration because all devices on the network can see these packets in plaintext and they contain a bunch of useful information.

And your issue with the JSON payload & spaces might come from the last 2 characters in the prefix - it needs to be the total length of the rest of the payload in hexadecimal. Using spaces will increase the size of the payload and if the value isn't the correct size then the command goes ignored.

@clach04
Copy link
Contributor

@clach04 clach04 commented Dec 3, 2017

@jepsonrob thanks for the length info, that's it for sure. I added support for this in clach04/python-tuya@fc4612f - I'm not sure if its a single byte for length or not (I've only coded it for a single byte and I've not yet added sanity check for that in case the payload goes above 255 bytes).

Thanks also for confirming about broadcast. Sadly, as per my previous comment, I'm not seeing this on my network (using code above i.e. something sitting on port 6666, I've not tried wiresharking the network). Any pointers?

I've created a wiki https://github.com/clach04/python-tuya/wiki to store progress and other useful related docs. E.g. I figured out the timer for the SM-PW701U device.

@jepsonrob
Copy link
Contributor Author

@jepsonrob jepsonrob commented Dec 3, 2017

@clach04 - try using this python script and see if anything comes through: it's working for me!

from socket import *
s=socket(AF_INET, SOCK_DGRAM)
s.bind(('',6666))
m=s.recvfrom(1024)
print m[0] 

And yeah I've only had it working for a single byte which is driving me crazy because the payload I need is over 255. Interestingly though, when I'm looking at the packets sent in Wireshark there's never anything over 255 bytes in size! I feel like this means I'm getting something wrong with my JSON payload and it's coming in too large, but I can't quite figure out how to decrypt the outgoing packets so I can't see the intended behaviour.

Nice work on the python version by the way! That wiki is a useful resource - I'm going to write a no-stupid-questions type of tutorial for this we've got it working with other devices, probably just to help people with IFTTT integration, and I'll link out to that for further reading.

@clach04
Copy link
Contributor

@clach04 clach04 commented Dec 3, 2017

@jepsonrob that script worked fine. My script also worked fine this morning (not sure why, maybe too tired last night).

Interesting notes:

  • I'm testing on Windows at the moment
  • python script only works if I'm on the WiFi network, being on the same network via a wire doesn't work (I thought I tested this last night but maybe was not testing with py2) - EDIT looks like this was a Windows firewall issue, specific Python process blocked on certain networks
  • python script only works for me with Python 2 (change print to add parens for py3), under Python 3 I do not see any packets - this one still confuses me. Not sure if this my machine, Windows, etc. - EDIT looks like this was a Windows firewall issue, specific Python process blocked on certain networks
  • node script above does NOT work for me (possible same root cause as py3 failure?) - EDIT gonna guess this was a firewall issue too

@jepsonrob script (slightly modified):

from socket import socket, AF_INET, SOCK_DGRAM

s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', 6666))
m = s.recvfrom(1024)
print(repr(m[0]))

My script:

# discover devices
# NOTE for my devices this only works with Python 2.6
# py3.6.1 runs but never reports packets

import socket
import struct


host_port = 6666
host_ip = '239.255.255.250'

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.bind(('', host_port))

mreq = struct.pack('4sl', socket.inet_aton(host_ip), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

try:
    while True:
        print('listening')
        data = sock.recvfrom(1024)
        raw_bytes, peer_info = data
        print(data)
finally:
    sock.close()
@clach04
Copy link
Contributor

@clach04 clach04 commented Dec 3, 2017

@jepsonrob for decrypting packets, try this (needs my Python module, https://github.com/clach04/python-tuya):

import base64
import time

import pytuya


key = 'YOUR_KEY_HERE'
packet = 'Python raw bytes'


PREFIX_LEN = 16
SUFFIX_LEN = 8
prefix = packet[:PREFIX_LEN]
json_crypted_plus_suffix = packet[PREFIX_LEN:]
json_crypted_len = ord(prefix[-1])
json_crypted_b64_with_header = json_crypted_plus_suffix[:json_crypted_len-SUFFIX_LEN]
version_str = json_crypted_b64_with_header[:3]
print('version_str (%d) %r' % (len(version_str), version_str))
hexdigest = json_crypted_b64_with_header[3:][:16]
print('hexdigest (%d) %r' % (len(hexdigest), hexdigest))
json_crypted_b64 = json_crypted_b64_with_header[3+16:]
suffix = packet[-SUFFIX_LEN:]  # assume we know length of end


print('packet (%d) %r' % (len(packet), packet))
print('prefix (%d) %r' % (len(prefix), prefix))
print('json_crypted_plus_suffix (%d) %r' % (len(json_crypted_plus_suffix), json_crypted_plus_suffix))
print('json_crypted_len %d' % (json_crypted_len))
print('suffix (%d) %r' % (len(suffix), suffix))

print('json_crypted_b64 (%d) %r' % (len(json_crypted_b64), json_crypted_b64))
cipher = pytuya.AESCipher(key)
json_raw = cipher.decrypt(json_crypted_b64)
print('json_raw (%d) %r' % (len(json_raw), json_raw))

EDIT only supports 255 lengths (could be updated if it turns out protocol supports it.

@codetheweb codetheweb changed the title Understanding the packet hex-encoded padding General Discussion Dec 3, 2017
@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Dec 4, 2017

FYI, the UID is now no longer required when constructing an instance thanks to @jepsonrob.

@Marcus-L
Copy link

@Marcus-L Marcus-L commented Dec 6, 2017

I read through #2 where accessing the Tuya API directly was briefly discussed. It would be preferable to be able to access the device IDs and localKeys without having to sniff traffic (especially since this appears to no longer be possible in recent versions of Android with the Packet Capture app).

It is possible to retrieve the Android App's API Key and Secret from the app source code. I believe these are the values:
screenshot_120517_095233_pm

However, I attempted to use the API documentation but was unable to successfully authenticate. Here's a fiddle that I was working with: https://dotnetfiddle.net/QzIVrP

I think the problem may be with the signing. When I logcat the Tuya Android app I see that the "sign" parameter is 40 characters long, however according to the documentation it should only be 32 characters since it's just a hex string representing a 128-bit MD5 hash.

screenshot_120517_102044_pm

Anyway, not sure if you'd want to fiddle around with it any more, but it really would be nice for the API to be able to fetch the device localKeys.

@clach04
Copy link
Contributor

@clach04 clach04 commented Dec 6, 2017

@Marcus-L keep us posted. I'm going to be a bit of a nay-sayer and say that I suspect we do not need API access to the cloud to register the device and get an encryption key. My gut tells me that registration of the device can be figured out.

RE packet capture problems, can you clarify which app/version and the problems you had?

I'm using https://play.google.com/store/apps/details?id=com.xenon.jinvoo&hl=en v1.0.3 which appears to be the latest and still works for me with https://play.google.com/store/apps/details?id=app.greyshirts.sslcapture&hl=en - but I'm thinking I should back it up and post here!

@clach04
Copy link
Contributor

@clach04 clach04 commented Dec 6, 2017

Forgot to add there is a chance the key is usable client side to interact with devices?

I've not tried to decompile it (and probably won't have time), is that how you made this progress?

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Dec 6, 2017

<rant>
Hey guys, just before you get any farther I wanted to make a quick comment. I will not allow working API keys extracted from the source code of other companies to be hard coded into my project. If you can use them to discover more information about the API and controlling the device locally, all well and good. But please don't expect me to add them. It's about ethics, not whether it's possible.

Besides, this was intended to be a project to control devices entirely locally - no calling back to home.
</rant>

Sorry if that came off as a bit too stern. Maybe you're not planning to do that :). In any case, good luck mapping out the API.

@Marcus-L
Copy link

@Marcus-L Marcus-L commented Dec 6, 2017

No worries @codetheweb, wasn't planning on hard-coding those keys into anything, Just exploring the API possibilities. As @clach04 mentioned it's likely to be possible to do everything locally. None of this would be necessary of course if the manufacturers would just release open tools, some documentation or even just rough specs! Or if the Tuya or Jinvoo app were to show the localKey settings. But here we are.

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Dec 6, 2017

@Marcus-L
Copy link

@Marcus-L Marcus-L commented Dec 7, 2017

No problem, thanks for the useful protocol info. I did a rough port of the api to .NET Standard here: https://github.com/Marcus-L/m4rcus.TuyaCore

I poked around a bit to try to see if I could find any more info on the discovery/localKeying process but didn't come up with anything useful.

@nijave
Copy link

@nijave nijave commented Dec 20, 2017

If you have a rooted Android phone, you can retrieve the settings from the app (Smart Life) data storage. The keys/configured devices are located at /data/data/com.tuya.smartlife/shared_prefs/dev_data_storage.xml

There's a string in there (the only data) called "tuya_data". You need to html entity decode the string and it contains a JSON string (yes, this is slightly ridiculous). Inside the JSON string are the keys.

@abarvinsky
Copy link

@abarvinsky abarvinsky commented Dec 21, 2017

Hi everyone, I just bought a couple of the outlets that work on this protocol but when I try to sniff the traffic using Charles, I don't get any GET requests like the ones mentioned here but only a few POST requests but it looks like the traffic is encrypted. I added tuyaus.com to the SSL Proxy in Charles but it did not help. I am not sure if it is the SSL encryption or Tuya is using their own encryption but it definitely looks like they changed the API or something like that.

Or maybe I am doing something wrong.
Any input is appreciated

@clach04
Copy link
Contributor

@clach04 clach04 commented Dec 21, 2017

@nijave I'm not sure where you read GET. I can definitely confirm you are looking for POST (I'd recommend looking at the response to a POST). See https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md - someone did comment stating they thought an app didn't contain the information any more. What app and device are you using? See my post above with the word "xenon" for where I know it still works.

@Exilit
Copy link

@Exilit Exilit commented Jan 4, 2018

The documentation from tuya themselves states the following:

Encryption key: The related interface key before activation is the first 16 characters of the authKey of the device. The key of the relevant interface after activation is secKey.

Moreover it says:

... ...
secKey Device and cloud communication key, obtained through the cloud-activated devId
localKey The device communicates data with the cloud MQTT server AES encryption key, which is returned with the secKey when the devId is activated in the cloud

If I get it right this means that there is a preset device specific key (the authKey). For the first communication during activation the first 8 byte(??) are used as AES encryption key. During the activation two other keys - the localKey AND the secKey- should be transmitted to the device. From there on secKey is used for HTTPS communication whereas localKey is used for MQTT communication.

But that can't be correct as I cannot see the secKey anywhere.
Moreover if it is correct, how do you think does the App know the authKey that is used for activation?

If the original app is able to retrieve the authKey from the devices, we should be able to do so also, don't we?

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Jan 4, 2018

Perhaps, but I doubt we can without also having an API key.

@steffest
Copy link

@steffest steffest commented May 6, 2020

Sorry for newb question, but how did you find KEY with HttpCanary?

@stianhoe

This is basically described in https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP_DEPRECATED.md

HttpCanary is used to capture the HTTPS POST requests from the Android app to the Tuya server. Then you can see to device ID and KEY in one of those post parameters when you add the device to the Android App.

@Jaja0624
Copy link

@Jaja0624 Jaja0624 commented May 22, 2020

If attempting to get key from via: https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md#linking-a-tuya-device is it possible to also use the device from the smart life app? I understand both will reset the device which would create a new local key. Does that mean it is not possible?

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented May 23, 2020

That is correct, currently there is not a good way to use your device with TuyaSmart and TuyAPI at the same time.

@TRSx80
Copy link

@TRSx80 TRSx80 commented Jun 26, 2020

At first I posted my own issue, but maybe this is not how things work around here, and you prefer questions of this sort over here? If so, apologies, I did not see any specific instructions to that effect. And it only took me 4 days to figure that out! 😄

In the meantime, I been working my way through this thread, but it's quite big thread...

OK, anyway, here are my original 2 posts (copied):

--

Hi guys,

Thank you for all your great work on this project! And for sharing it!

  1. If I am understanding the setup instructions correctly, you basically create a developer account, then use the command line tool to output all credentials you need to control your devices (including the all important "device key") to the console, is that right? You then use those credentials with tuyapi, perhaps plus some other wrapper, to control your devices using whatever HA controller / method of your choice (in my case OpenHAB, maybe with or without MQTT)... Correct so far?

If so, couple follow on questions:

  1. I don't have to install any "app" on my phone, nor create any (regular user / non developer) "account" (I think they call it "Smart Life"?) in order to do any of this? Is that also correct?

  2. I can from then on fully control the devices locally, without any longer needing any of Tuya's "cloud" crap (in other words, developer account is only required for registration, after which I can control everything locally)?

Have I got all of this correct? Because I am very privacy conscious person, who refuse to use any devices that need to "phone home" in order to work.

I had ordered some of these plugs with hopes of flashing Tasmota (or similar) on them, but unfortunately I learned that I bought some TW-02-based (WinnerMicro W600-based) devices which are not ESP8266 based, and therefore not supported by any alternative firmware. Leaving this way as perhaps one of only options for me (if I am understanding everything correctly).

--

I guess my biggest concern would be creating the developer account. I really do not want to share any of my real personal information with Tuya (or anyone really who I feel doesn't need it, which is pretty much everyone 😄 ), however it may be required for developer account?

What information do they ask for, and how thoroughly is it vetted (if at all)?

Any feedback from anyone who has already done so would be greatly appreciated.

--

@steffest
Copy link

@steffest steffest commented Jun 26, 2020

@TRSx80

I'm not 100% sure it's the same for your device - as it seems there are a LOT of different brands and version, but for me the instructions on https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP_DEPRECATED.md worked perfectly fine.
(Yes, I know they says "deprecated" :-) )
No need to create a developer account - you only have to manage sniffing the network traffic on your wifi network, which requires some fiddling as its HTTPS, but it's doable - I used HTTPCanary on a (non-rooted) Android device for that.

You can then extract the device ID and KEY you need to control the device from the POST parameters during the registration process.
To answer your question 3: yes: you can then control the device locally, without having to go through the Tuya cloud services.

During the time I used this approach, I only found 1 mayor flaw: each time your device gets reset, you have to reconnect and the DeviceID/KEY will be different, so you have to redo the process, at which point the device do needs to phone home.
For a light bulb, this happens for example when somebody switch the light on and of rapidly a few times.

A minor annoying part is that the IP address of the device changes every once and a while, and you have to scan the network again to find it. minor issue, maybe you even have a router where you can assign fixed IPs to devices.

@TRSx80
Copy link

@TRSx80 TRSx80 commented Jun 26, 2020

@steffest,

Thank you so much for the reply. I suppose now I see the wisdom in one big thread, where hundreds of people with similar interest all posted before and thereby also get notified of new posts. Like a mini forum, all on one thread. Brilliant!

I have no problem with rooted or old versions of Android (have all of above, as well as other tools to potentially MitM), nor with transient IP address on LAN as I run OpenWRT router as well as dnsmasq, etc...

However this "reset" issue concerns me, as it sounds sooner or later you will need to end up "phoning home" to Tuya? I suppose this is why the "developer account" method is now the recommended way. Is there any place I could find more information on what might cause this "reset"? Could I avoid any particular list of behaviors to make this not happen? In a reliable way?

I already read about not using the Smart Life app in conjunction, also I suppose I would be blocking any "phoning home" at my router, would that be enough or are there more things to do? And even if I do all those things, will it be enough to prevent this "reset" and need to "phone home" again?

Or, maybe I am still best just to get developer account? Any feedback on either route would still be very welcome.

Happy Friday, everybody! 🍻

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Jun 26, 2020

At first I posted my own issue, but maybe this is not how things work around here, and you prefer questions of this sort over here? If so, apologies, I did not see any specific instructions to that effect. And it only took me 4 days to figure that out! 😄

Sorry, I've been busy with other stuff lately. I actually prefer new issues so it's easier for people in the future to search and find answers, but either works.

@trevortrusty
Copy link

@trevortrusty trevortrusty commented Jul 13, 2020

How would I extract the IP of a device into a variable so that it could be printed to the console?

@TRSx80
Copy link

@TRSx80 TRSx80 commented Jul 14, 2020

How would I extract the IP of a device into a variable so that it could be printed to the console?

With tuyapi/cli I guess? I never used the tool, but the following might be helpful (from README):

Usage: cli [options] [command]

    get [options]       get a property on a device
    list                list all locally saved devices
@johnwalicki
Copy link

@johnwalicki johnwalicki commented Jul 14, 2020

I have a Gosund / Tuya WiFi powerstrip. I created a Tuya login account, app, linked device and can successfully run
$ tuya-cli wizard
which returns
[
{
name: 'SmartPowerStrip',
id: 'mydeviceidmacaddr',
key: 'aaaaaaaaaaaaa'
}
]

But when I run
$ tuya-cli get --all --ip 192.168.1.167 --id mydeviceidmacaddr --key aaaaaaaaaaaa
it never returns.
I try using the node-red-contrib-tuya-smart node and it disconnects immediately.

I can control the powerstrip from iOS and Android apps.
I would like to control the powerstrip from a Node-RED flow. Not certain what is wrong.

@TRSx80
Copy link

@TRSx80 TRSx80 commented Jul 14, 2020

from iOS and Android apps.

Doesn't it somehow "reset" your key or something when you do this?

@johnwalicki
Copy link

@johnwalicki johnwalicki commented Jul 14, 2020

Looking through ~/.node-red/node_modules/tuyapi/index.js I see that it creates UDP listeners on ports 6666/6667
I opened them on my firewalld. At least I was able to talk with the powerstrip. The Feb14 script by @Deses has been helpful.

$ sudo firewall-cmd --permanent --add-port=6666/udp
success
$ sudo firewall-cmd --permanent --add-port=6667/udp
success
$ sudo firewall-cmd --reload

@johnwalicki
Copy link

@johnwalicki johnwalicki commented Jul 14, 2020

Watching UDP traffic on port 6667, I see periodic encrypted data from the powerstrip.

$ sudo tcpdump -i any -c20 -nn -A port 6667
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
15:49:19.286495 IP 192.168.1.167.49154 > 255.255.255.255.6667: UDP, length 188
E..........,...............:..U...................fgo3i.....2..*.4.......j..F.J.......t...8.3..ln .t.Z......	...L..l
..A;.../..... ...>S$...^.1".....X..[#i~....*....>0.N....Z_.._J.A..R.^..U../v..j.4..f....."........U
15:49:24.285108 IP 192.168.1.167.49154 > 255.255.255.255.6667: UDP, length 188
E..........+...............:..U...................fgo3i.....2..*.4.......j..F.J.......t...8.3..ln .t.Z......	...L..l
..A;.../..... ...>S$...^.1".....X..[#i~....*....>0.N....Z_.._J.A..R.^..U../v..j.4..f....."........U

Turning debug on in the ~/.node-red/node_modules/tuyapi/index.js
I see that the decrypted messages are:

Pinging 192.168.1.167
Received data: 000055aa00000000000000090000000c00000000b051ab030000aa55
Parsed:
{ payload: false, leftover: false, commandByte: 9, sequenceN: 0 }
Pong from 192.168.1.167
@johnwalicki
Copy link

@johnwalicki johnwalicki commented Jul 14, 2020

Essentially, I can write a node app using the tuyapi to control the powerstrip successfully. Proved that it works!
What I really want is to use the Node-RED node-red-contrib-tuya-smart nodes. That doesn't works.

@johnwalicki
Copy link

@johnwalicki johnwalicki commented Jul 14, 2020

Hmm - node-red-contrib-tuya-smart has a hard dependency on tuyapi 3.2.3. I'll try to bump it to tuyapi 5.x

@johnwalicki
Copy link

@johnwalicki johnwalicki commented Jul 14, 2020

I've given up on node-red-contrib-tuya-smart and have successfully configured node-red-contrib-tuya-local from
https://github.com/subzero79/node-red-contrib-tuya-local
3 hours of investigation wasted.

@TRSx80
Copy link

@TRSx80 TRSx80 commented Jul 14, 2020

Perhaps not the outcome you were looking for, but an (hopefully, workable) outcome nonetheless.

Therefore, IMHO, the time was not "wasted." 😉

@beele
Copy link

@beele beele commented Aug 17, 2020

Once you have the keys, is it possible to remove the devices from the tuya app and keep using them with this project?

@charliebudd
Copy link

@charliebudd charliebudd commented Aug 18, 2020

Hi all, Ive tried running the provided example but device.find times out. I feel like I've been through all the trouble shooting I can find but it just wont connect. I have the device registered on the tuya cloud development platform and have used the tuya-cli wizard to get my devices key so I know its correct. What am I missing? (and yes the device is powered on with no other active connections). Thanks for any help!

Edit: Running a tuya-cli get command also times out even though im using the info tuya-cli has provided me
Further Edit: tuya-cli get command does work if I omit the ip address

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Aug 19, 2020

@beele if you extracted the keys after linking your device through the app, you cannot remove it. That will reset the device and invalidate the keys.

@charliebudd if it works when you provide your IP address it's likely an issue with your network. Not much TuyAPI can do about it. If you still believe that there's a bug with TuyAPI, please open a new issue.

@charliebudd
Copy link

@charliebudd charliebudd commented Aug 19, 2020

So Ive used a packet sniffer (Wireshark) to isolate the traffic when I make a successful tuya-cli get call. When I run the synchronous sample script it stalls when connecting to device, neither timing out or erroring. In wire shark I see periodic traffic between my computer and the smart device while the script is awaiting the device.connect call. Im not much of a web developer so im struggling to debug the cause but this seams like odd behaviour.

@codetheweb
Copy link
Owner

@codetheweb codetheweb commented Aug 19, 2020

Please open a new issue with additional details if you believe there's a bug or want further support. A network dump would be helpful.

@briggitteorellana
Copy link

@briggitteorellana briggitteorellana commented Sep 17, 2020

Al observar el tráfico UDP en el puerto 6667, veo datos cifrados periódicos de la tira de alimentación.

$ sudo tcpdump -i any -c20 -nn -A port 6667
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
15:49:19.286495 IP 192.168.1.167.49154 > 255.255.255.255.6667: UDP, length 188
E..........,...............:..U...................fgo3i.....2..*.4.......j..F.J.......t...8.3..ln .t.Z......	...L..l
..A;.../..... ...>S$...^.1".....X..[#i~....*....>0.N....Z_.._J.A..R.^..U../v..j.4..f....."........U
15:49:24.285108 IP 192.168.1.167.49154 > 255.255.255.255.6667: UDP, length 188
E..........+...............:..U...................fgo3i.....2..*.4.......j..F.J.......t...8.3..ln .t.Z......	...L..l
..A;.../..... ...>S$...^.1".....X..[#i~....*....>0.N....Z_.._J.A..R.^..U../v..j.4..f....."........U

Al activar la depuración en ~ / .node-red / node_modules / tuyapi / index.js
, veo que los mensajes descifrados son:

Pinging 192.168.1.167
Received data: 000055aa00000000000000090000000c00000000b051ab030000aa55
Parsed:
{ payload: false, leftover: false, commandByte: 9, sequenceN: 0 }
Pong from 192.168.1.167

How do I get a result like this in node red??

@89jd
Copy link

@89jd 89jd commented Sep 22, 2020

Hi,

I created a few wrappers around this library to be used within python. The idea was that seen as this is consistently maintained, I wrote an IPC wrapper that uses file descriptors to communicate. The first github repo below shows my findings on how the roborock vacuum communicates, and the rest are the IPC node code, the python implementation for the IPC, a library for communicating via roborock, and finally a wrapper round it all to be used by home assistant. Hopefully it is useful to some other people out their too

https://github.com/89jd/roborock_comms

https://github.com/89jd/tuyapi-ipc

https://github.com/89jd/pytuyapi-ipc

https://github.com/89jd/pyroborock

https://github.com/89jd/hass-roborock

@sanyogthescholar
Copy link

@sanyogthescholar sanyogthescholar commented Oct 5, 2020

Hello everyone,
Sorry if this has been asked before, but when I went to register for Tuya IOT cloud, it says that it has a free trial only for three months. Does that mean I won't be able to control my devices with this API after 3 months unless I pay?
Is there some sort of always free plan?

@charliebudd
Copy link

@charliebudd charliebudd commented Oct 5, 2020

You only need the Tuya platform to access the data that lets you connect to the device (IP, ID, and Key if my memory is correct). This api uses a LAN connection so you will still be able to use your solution after your trial ends.

@jeth318
Copy link

@jeth318 jeth318 commented Oct 10, 2020

Hey! I'm trying to access my robot vacuum cleaner. I manage to connect to the device, but the output from the device seems to be encrypted or just some wierd language. Can someone understand why I get this?

tuyapi

@jeth318
Copy link

@jeth318 jeth318 commented Oct 10, 2020

Hey! I'm trying to access my robot vacuum cleaner. I manage to connect to the device, but the output from the device seems to be encrypted or just some wierd language. Can someone understand why I get this?

tuyapi

Oh I used the wrong device key, now it's decrypted and readable.

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

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.