codetheweb / tuyapi

🌧 An easy-to-use API for devices that use Tuya's cloud services. Documentation: https://codetheweb.github.io/tuyapi.
MIT License
2.06k stars 339 forks source link

resolveIds() never returns #19

Closed jmschonfeld closed 6 years ago

jmschonfeld commented 6 years ago

The current code I'm using is:

let tuya = new TuyaDevice({
  id: args.id,
  key: 'XXXXXXXXXXXXXXX'});
console.log("Resolving IP for device '" + args.id + "'...");
tuya.resolveIds().then(() => {
  console.log("IDs resolved, performing action...");
  if (args.action == 'status') {
    tuya.get().then(status => {
      console.log("status=" + status);
    });
  } else if (args.action == 'on') {
    tuya.set({set: true})
  } else if (args.action == 'off') {
    tuya.set({set: false})
  } else {
    process.exit(1);
  }

});

I see it output Resolving IP for... but it never makes it to IDs resolved..., suggestions?

codetheweb commented 6 years ago

As long as the ID is correct and you don't have any kind of weird network setup it should work just fine. Try starting your script with DEBUG=* node script.js and see if there's anything in the output that helps (it should log all received UDP messages).

If you can't get it to work, you can always pass in the IP manually.

jmschonfeld commented 6 years ago

I have tried using DEBUG=* and specifying the ip directly. I have run a port scan on the IP of my device and confirmed that port 6668 is an open TCP port. When running DEBUG=* node script.js I see:

  TuyAPI Device(s):  +0ms
  TuyAPI [ { id: 'XXXXXXXXXXXXX',
  TuyAPI     ip: 'XXX.XXX.XXX.XXX',
  TuyAPI     key: 'XXXXXXXXXXXXXX',
  TuyAPI     type: 'outlet',
  TuyAPI     uid: '',
  TuyAPI     port: 6668,
  TuyAPI     version: 3.1,
  TuyAPI     cipher: 
  TuyAPI      { algorithm: [Object],
  TuyAPI        mode: [Object],
  TuyAPI        blockSize: 16,
  TuyAPI        _finish: false,
  TuyAPI        _input: null,
  TuyAPI        output: null,
  TuyAPI        _op: [Function],
  TuyAPI        _decrypt: false } } ] +13ms

  TuyAPI Payload:  +31ms
  TuyAPI { gwId: 'XXXXXXXXXXXXXX', devId: 'XXXXXXXXXXXXXXX' } +0ms
  TuyAPI Sending this data:  XXXXXXXX...XXXXXXXXXXXXX +12ms

And then the program does nothing and waits for a reply from the TuyaAPI (no reply).

codetheweb commented 6 years ago

Weird. It should print something, whether an error or returned data, but the fact that it doesn't even resolve with an error is strange (because if wrongly-formatted data is sent to a device, the device returns a TCP error). The only thing I can think of is that communication between your computer and device is not working for some reason.

Try passing through all traffic from your phone to your computer with a SOCKS proxy (I think you can do this in Charles), and see if your phone is still able to control it.

ghost commented 6 years ago

I am experiencing exactly the same problem. Usually it does not return but sometimes I get this error:

[11/02/2018 21:15:59.968] [ERROR] (node:21047) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error communicating with device. Make sure nothing else is trying to control it or connected to it.

I try using your API from a simple node application with a web action and I am using ID, key and IP address of my device.

Also I tried using it with homebridge tuya api, it has the same issues - sometimes it works but often homebridge reports that the device is not reachable.

Did tuya change something in their API?

Their SmartLife app works without any issues and I can turn on and off my devices any time. Also Alexa works without any issues, so it must be something wrong with the API or your module

unparagoned commented 6 years ago

I've notice a similar issue where it binds properly to the port but can't see any of the messages from the tuya devices. This was with a separate python script which didn't have a timeout and just hung so it might be a wider issue than just your script. (I manually sent a message on that port to get it to return so it was properly binding to the port and could see messages on that port). So in some situations either the actual devices stop broadcasting to the network or the computer can't see any of the broadcasts from the device. Maybe in some situations the tuya devices are essentially DOSed by tuyapi taking them offline?

ghost commented 6 years ago

@unparagoned: I have the same theory, but I don't think it is a DOS. I think that there is no timeout and when tuyapi connects to a device and hangs, it never times out, thus making the device unaccessible. I have noticed that WHILE the device is unaccessible for the tuyapi calls it IS ACCESSIBLE for the SmartLife app and for Alexa and for IFTTT, so this is solely the issue of tuyapi. I will have a looksee at the tuyapi code when I have a chance to see if there is something obvious there. Meanwhile the solution I am using is to restart homebridge every X minutes and have PM2 restart your node app every Y minutes to release any calls that are stuck.

unparagoned commented 6 years ago

@starblastresearch I think those other services use the cloud interface. So it's more of a local connection issue rather than just tuyapi.

Edit: I had issues are an hour or so. I was able to disable the internet and and monitored what the jinvoo app does. First I noticed that while I had closed all my apps on the phone, the jinvoo app was going map trying to get a connection to one of thousands of servers set up. The only other app that looked like it was trying to do anything was whatsapp. Anyway The app in offline mode can get the device status and control it fine. I looked at the packets and they look like they are in the format used by tuyapi, over tcp connecting to 6668. So I don't know why the app worked but script didn't. I tried the tuyapi and my own python passive monitoring script on (6666) and neither worked on my server or personal devices. So I'm stumped.

Edit 2: It looks like the devices aren't advertising their id and ip like usual. I tried checking with multiple scripts with various computers, with various devices. So either the route cause is knocking out multiple devices, or maybe the router is dropping some of the broadcasts for some reason. A reboot of my router did fix it, but that doesn't really mean too much.

kryztoval commented 6 years ago

I see the exact same behavior, it starts and does nothing. No error, no timeout, nothing.

When i try the DEBUG=* I get a lot of receiving UDP and parsing to JSON lines, but it never stops.

The only place I got the information from was an http packet from wireshark that reads:

Object
    Member Key: schema
        String value [truncated]: [{"mode":"rw","property":{"type":"bool"},"id":1,"type":"obj"},{"mode":"rw","property":{"type":"bool"},"id":2,"type":"obj"},{"mode":"rw","property":{"type":"bool"},"id":3,"type":"obj"},{"mode":"rw","property":{"typ
        Key: schema
    Member Key: uid
        String value: /0-9a-zA-Z/
        Key: uid
    Member Key: devEtag
        String value: /0-9a-z/
        Key: devEtag
    Member Key: secKey
        String value: /0-9a-f/
        Key: secKey
    Member Key: schemaId
        String value: /0-9a-z/
        Key: schemaId
    Member Key: localKey
        String value: /0-9a-f/
        Key: localKey

Values where edited with their most likely character representation.

I am using "uid" and "localKey" from that list. I also tried "uid" and "secKey", besides those I don't know what other values to try.

codetheweb commented 6 years ago

I've added a timeout for resolving device IDs to IPs in v2.0.3. Update by running npm install tuyapi.

I realize this only partly addresses the issues you guys are having, but I'm pretty sure that in instances when TuyAPI receives no UDP data it's the networks fault.

Closing this issue for now. If you can offer proof that TuyAPI doesn't receive UDP packets and it's not your network's fault, please comment and I'll reopen this.