Giter VIP home page Giter VIP logo

tuyapi's Introduction

TuyAPI ๐ŸŒง ๐Ÿ”Œ

XO code style Build Status Coverage Status Node Version

A library for communicating with devices that use the Tuya cloud network. These devices are branded under many different names, but if your device works with the TuyaSmart app or port 6668 is open on your device chances are this library will work.

Installation

npm install codetheweb/tuyapi

Basic Usage

See the setup instructions for how to find the needed parameters.

These examples should report the current status, set the default property to the opposite of what it currently is, then report the changed status. They will need to be adapted if your device does not have a boolean property at index 1 (i.e. it doesn't have an on/off property). Index 20 seems to be another somewhat common on/off property.

Asynchronous (event based, recommended)

const TuyAPI = require('tuyapi');

const device = new TuyAPI({
  id: 'xxxxxxxxxxxxxxxxxxxx',
  key: 'xxxxxxxxxxxxxxxx'});

let stateHasChanged = false;

// Find device on network
device.find().then(() => {
  // Connect to device
  device.connect();
});

// Add event listeners
device.on('connected', () => {
  console.log('Connected to device!');
});

device.on('disconnected', () => {
  console.log('Disconnected from device.');
});

device.on('error', error => {
  console.log('Error!', error);
});

device.on('data', data => {
  console.log('Data from device:', data);

  console.log(`Boolean status of default property: ${data.dps['1']}.`);

  // Set default property to opposite
  if (!stateHasChanged) {
    device.set({set: !(data.dps['1'])});

    // Otherwise we'll be stuck in an endless
    // loop of toggling the state.
    stateHasChanged = true;
  }
});

// Disconnect after 10 seconds
setTimeout(() => { device.disconnect(); }, 10000);

Synchronous

const TuyAPI = require('tuyapi');

const device = new TuyAPI({
  id: 'xxxxxxxxxxxxxxxxxxxx',
  key: 'xxxxxxxxxxxxxxxx',
  issueGetOnConnect: false});

(async () => {
  await device.find();

  await device.connect();

  let status = await device.get();

  console.log(`Current status: ${status}.`);

  await device.set({set: !status});

  status = await device.get();

  console.log(`New status: ${status}.`);

  device.disconnect();
})();

Data not updating?

Some new devices don't send data updates if the app isn't open.

These devices need to be "forced" to send updates. You can do so by calling refresh() (see docs), which will emit a dp-refresh event.

const TuyAPI = require('tuyapi');

const device = new TuyAPI({
    id: 'xxxxxxxxxxxxxxxxxxxx',
    key: 'xxxxxxxxxxxxxxxx',
    ip: 'xxx.xxx.xxx.xxx',
    version: '3.3',
    issueRefreshOnConnect: true});

// Find device on network
device.find().then(() => {
    // Connect to device
    device.connect();
});

// Add event listeners
device.on('connected', () => {
    console.log('Connected to device!');
});

device.on('disconnected', () => {
    console.log('Disconnected from device.');
});

device.on('error', error => {
    console.log('Error!', error);
});

device.on('dp-refresh', data => {
    console.log('DP_REFRESH data from device: ', data);
});

device.on('data', data => {
    console.log('DATA from device: ', data);

});

// Disconnect after 10 seconds
setTimeout(() => { device.disconnect(); }, 1000);

๐Ÿ“ Notes

  • Only one TCP connection can be in use with a device at once. If using this, do not have the app on your phone open.
  • Some devices ship with older firmware that may not work with tuyapi. If you're experiencing issues, please try updating the device's firmware in the official app.
  • Newer firmware may use protocol 3.3. If you are not using find(), you will need to manually pass version: 3.3 to the constructor.
  • TuyAPI does not support sensors due to the fact that they only connect to the network when their state changes. There are no plans to add support as it's out of scope to intercept network requests.
  • The key parameter for devices changes every time a device is removed and re-added to the TuyaSmart app. If you're getting decrypt errors, try getting the key again - it might have changed.

๐Ÿ““ Documentation

See the docs.

Current State & the Future of TuyAPI

The goal of this repository specifically is to provide a bit of a middle ground between implementing everything from scratch and having everything handled for you.

I realize this is a bit wishy-washy and most users would prefer one or the other. I started a new library a while ago to address this and incorporate some of the lessons we've learned over the years: @tuyapi/driver. The intention is that this library would be fairly low-level, and then more user-friendly libraries could be built on top of it to provide common functionality for, say, setting RGB light values (probably named @tuyapi/devices).

Unfortunately, not much progress has been made in that regard for a few reasons. First, besides the occasional coffee (thank you ๐Ÿ˜€) I don't get paid for this. And it's hard to be motivated to work on it when I don't actually use it day-to-day. For lack of a beter explanation, it's just not "fun" anymore. Also: trying to play wack-a-mole with a large corporation is kinda exhausting.

TL;DR: all that to say that I personally will not be further developing Tuya-related projects for the foreseeable future besides fixing reproducable bugs. I plan to still respond to support requests and bug reports, but please be patient. ๐Ÿ˜€

Contributing

See CONTRIBUTING.

Contributors

(If you're not on the above list, open a PR.)

Related

Flash alternative firmware

  • tuya-convert a project that allows you to flash custom firmware OTA on devices

Ports

Clients for Tuya's Cloud

Projects built with TuyAPI

To add your project to either of the above lists, please open a pull request.

forthebadge forthebadge

tuyapi's People

Contributors

1dontex1st avatar alexlmiller avatar apollon77 avatar charles-benedito avatar cj922 avatar clach04 avatar codetheweb avatar dkrahmer avatar dresende avatar duncte123 avatar ellneal avatar emilsodergren avatar fliegenklatsch avatar gautampanchal94 avatar haimkastner avatar hgross avatar imbenwolf avatar jasonacox avatar jepsonrob avatar jpillora avatar kueblc avatar mo5h avatar neojski avatar renovate-bot avatar renovate[bot] avatar rubenkelevra avatar thepheonixguy avatar tjfontaine avatar tsightler avatar unparagoned avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tuyapi's Issues

Change to throw on index.js line 281

I'm having issues since the change to throw on index.js line 281. It seems execution completely halts and does not get caught when _send is being executed, if there is an error. I get:

Scripts/node_modules/tuyapi/index.js:281
          throw err;
          ^

Error: Error communicating with device. Make sure nothing else is trying to control it or connected to it.
    at _errnoException (util.js:992:11)
    at TCP.onread (net.js:618:25)

,though the former error(err) line seemed to be functional. I'm not a Node expert but it seems now I can't rely on the reject Promise from the set method such that I can perform retries because I don't actually get it. Any thoughts?

Prefix / Suffix from requests.json

Hi,

In requests.json how did you find the prefix and suffix for status, on and off?

I can use your sample code to get the status of my Smart Plug without any issues and can switch on but not off. From a plug switched off to on I do get an error but it does come on:

Status: false
Result of setting status to true: true
SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at _send (/home/pi/node_modules/tuyapi/index.js:62:21)
    at Socket.client.on.data (/home/pi/node_modules/tuyapi/index.js:137:14)
    at emitOne (events.js:115:13)
    at Socket.emit (events.js:210:7)
    at addChunk (_stream_readable.js:250:12)
    at readableAddChunk (_stream_readable.js:237:11)
    at Socket.Readable.push (_stream_readable.js:195:10)
    at TCP.onread (net.js:586:20)

But then I try to turn off again

Status: true
{ Error: read ECONNRESET
    at exports._errnoException (util.js:1026:11)
    at TCP.onread (net.js:607:25) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }

Could the suffix / prefix be my issue? My Smart Plug is a UK version, not sure if that could be the issue (https://www.amazon.co.uk/Wireless-Switch-Function-Android-Devices/dp/B071SDNGW2/ref=sr_1_3?ie=UTF8&qid=1510959884&sr=8-3&keywords=smart+plug)?

Thanks

Get works but set doesn't

Describe the bug
Unable to use tuya.set()

To Reproduce

const TuyaDevice = require('tuyapi');

let tuya = new TuyaDevice({
  id: '012005726001946e7f40',
  key: 'xxxxxxxxxxxxxxxx',
  ip: '192.168.0.3'});

tuya.get().then(status => {
  console.log('Status:', status);

  tuya.set({set: !status}).then(result => {
    console.log('Result of setting status to ' + !status + ': ' + result);

    tuya.get().then(status => {
      console.log('New status:', status);
      return;
    });
  });
});

Expected behavior
Expect the lights to go off?

Debug Output

  TuyAPI Device:  +0ms
  TuyAPI { id: '012005726001946e7f40',
  TuyAPI   key: 'xxxxxxxxxxxxxxxx',
  TuyAPI   ip: '192.168.0.3',
  TuyAPI   port: 6668,
  TuyAPI   version: 3.1,
  TuyAPI   cipher:
  TuyAPI    TuyaCipher {
  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 },
  TuyAPI      decipher:
  TuyAPI       { algorithm: [Object],
  TuyAPI         mode: [Object],
  TuyAPI         blockSize: 16,
  TuyAPI         _finish: false,
  TuyAPI         _input: null,
  TuyAPI         output: null,
  TuyAPI         _op: [Function],
  TuyAPI         _decrypt: true },
  TuyAPI      version: 3.1 } } +1ms
  TuyAPI Payload:  { gwId: '012005726001946e7f40', devId: '012005726001946e7f40' } +2ms
  TuyAPI Socket attempt 1 +2ms
  TuyAPI Sending this data:  000055aa000000000000000a000000467b2267774964223a223031323030353732363030313934366537663430222c226465764964223a223031323030353732363030313934366537663430227d000000000000aa55 +0ms
  TuyAPI Socket connected. +7ms
  TuyAPI Received data back: +21ms
  TuyAPI 000055aa000000000000000a00000114000000007b226465764964223a223031323030353732363030313934366537663430222c22647073223a7b2231223a747275652c2232223a227768697465222c2233223a3235352c2234223a3235352c2235223a226666303030303030303066666666222c2236223a223030666630303030303030303030222c2237223a226666666635303031303066663030222c2238223a226666666638303033666630303030303066663030303030306666303030303030303030303030303030303030222c2239223a226666666635303031666630303030222c223130223a226666666630353035666630303030303066663030666666663030666630306666303030306666303030303030227d7de27ffec00000aa55 +0ms
Status: true
  TuyAPI Payload: +2ms
  TuyAPI { devId: '012005726001946e7f40',
  TuyAPI   uid: '',
  TuyAPI   t: '1534822576',
  TuyAPI   dps: { '1': false } } +0ms
  TuyAPI Socket attempt 1 +2ms
  TuyAPI Sending this data:  000055aa000000000000000700000087332e316532626163616135653561633834616546476b39646c4379644c4372414a524b736e4634664851646a4138624e33724973577443384d5346547974637648666d4f693557676c47794d6837675562616447522f77712b2b324e6b62336f3577505955312f4d4d685151564551797462737a6e356a5a6156374f6e513d000000000000aa55 +0ms
  TuyAPI Socket connected. +23ms
  TuyAPI Socket attempt 2 +6s
  TuyAPI Sending this data:  000055aa000000000000000700000087332e316532626163616135653561633834616546476b39646c4379644c4372414a524b736e4634664851646a4138624e33724973577443384d5346547974637648666d4f693557676c47794d6837675562616447522f77712b2b324e6b62336f3577505955312f4d4d685151564551797462737a6e356a5a6156374f6e513d000000000000aa55 +0ms

Desktop (please complete the following information):

  • OS: Linux
  • OS Version Ubuntu 16.04
  • Node Version v10.8.0

Updating the firmware trough local API

As I find it hard to find some information on if sombody managed to update the firmware of a tuya device utilizing any kind of OTA update, I thought this might be the right place to ask.

Device(s) Failed to be registered!

I've created the Tuya account and obtained the ID and Key from the site.

When I go to add a device I get the following error.
ร— Device(s) failed to be registered!
Error: Timed out wating for device(s) to connect to cloud
at Promise (C:\Users\xxxxxx\AppData\Roaming\npm\node_modules@tuyapi\cli\node_modules@tuyapi\cloud\index.js:275:12)
at

I'm using this smart plug https://www.amazon.com/gp/product/B07CHMDP1G/ref=oh_aui_detailpage_o09_s00?ie=UTF8&psc=1 with the Smart Life app. Running Charles on my iPhone I can confirm it's communicating through the Tuya Cloud. I put the switch in pairing mode but the wizard never finds it. Instantly can add it back to the Smart Life app though.

I use the iOS APP KEY from Tuya for apikey in the wizard and iOS APP Secret from Tuya for apisecret in the wizard. Am I doing something wrong?

Local permissions error on macOS

I keep getting an issue when running tuya-cli link-wizard around permission access

Error: EACCES: permission denied, open '/Users/James/.config/configstore/@tuyapi/cli.json'
You don't have access to this file.

Im a total noob so please help me in child friendly comms!

Tuyapi getter functions work, but setters time out

I had both getters and setters working before, but now only the getter functions work.
I can still control the smart bulb using the android app.

If I run this test script

const TuyaDevice = require( 'tuyapi' );

let tuya = new TuyaDevice({
	id: 'abcdefghij1234567890',
	key: 'abcdef1234567890',
	ip: '192.168.1.120' });

tuya.get().then( status => {
	console.log( 'Status:', status );
	
	tuya.get( { schema: true } ).then( schema => {
		console.log( 'Schema:', schema );
		
		tuya.set( { dps: 2, set: 128 } ).then( status => {
			console.log( 'StatSet:', status );
		}).catch( err => { console.log( 'err:', err ) } );
	});
});

It prints:

Status: true
Schema: { devId: 'abcdefghij1234567890',
dps: { '1': true, '2': 140, '3': 0 } }
err: Error: Timeout waiting for response
at Timeout._sendTimeout.setTimeout [as _onTimeout] (C:\Users\abc\node_modules\tuyapi\index.js:301:16)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)

I've made sure the android app is not connected to the bulb when running the scripts.
I'm rather puzzled. Any ideas what could be wrong?

It works but the process don't end

Hello. The script works fine, I can switch my plug on/off but, the node process doesn't quit and I get an infinite loop :

Status: true
Result of setting status to false: true
New status: false
{ Error: read ECONNRESET
    at exports._errnoException (util.js:1020:11)
    at TCP.onread (net.js:568:26) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
{ Error: read ECONNRESET
    at exports._errnoException (util.js:1020:11)
    at TCP.onread (net.js:568:26) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
[again and again]

running on ubuntu 17.10 node v6.11.4 and rasbpian node v6.12.2.
Any clue ?

Notice I also get the same problem with only a getStatus :

    const TuyaDevice = require('tuyapi');

    var tuya = new TuyaDevice({
      type: 'outlet',
      ip: '192.168.0.18',
      id: 'xxxx',
      key: 'xxxx'
    });
    tuya.getStatus(function(error, status) {
      if (error) { return console.log(error); }
      console.log('Status: ' + status);
    });

Automatically aquire needed parameters

I am able to get all the info I outlined in this post:
https://github.com/python-tuya/python-tuya/issues/1#issuecomment-338845744

Yet still have no idea where to find the UID and KEY values.

I tried to use the Charles app and had my phone send all traffic through a socks 5 proxy to Charles and I'm still not seeing the local key or uid values. Maybe the first json string is unencrypted getStatus. I want to say that my ssl cert reversing things just arn't working on this. How did you go about de-ssl-ing the packets?

Here is a sample of a turn on and off on the port 6668:

..U..............WA=...U..U..................Q.....U..U........
...F{"devId":"002009262c3ae817e19a","gwId":"002009262c3ae817e19a"}.%.}...U..U........
...Y....{"devId":"002009262c3ae817e19a","dps":{"1":false,"2":0,"4":0,"5":0,"6":1231}}m..u...U..U.............3.137ed7a48ff271e52PZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrH+Cke6uc2p1Ffl2AYvLF2rJ/ngc/EJeIXiGOrY9vFbniEA7LmOkCK66N6cb80iql2E6CfiCza+ivc2mlfUf/R6#..+...U..U.................x.p....U..U.................3.18cc58581a5d5a855PZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrExYLyT9xR3tTqTGAN2CNEnUVALV5jheBKxuaLpNTjRUjLaZ1j+jBoZrAxZ3zcs680=.w.....U..U.............3.13e5530644a4a031bPZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrHZfccCsWIkuo2QNShDjqQTc3M4KsH/I2MnjRbt/S9QjCEA7LmOkCK66N6cb80iql2E6CfiCza+ivc2mlfUf/R6..V....U..U.................x.p....U..U.................3.193b1f16eed69c377PZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrGWjcMctZYp4nF91mDoV1IAimI/NF3StveQCtVjcSl9SrP68joOZ7crLpwap1yx6Yg=%..c...U..U.............3.1dc00201b701beaebPZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrH1KeS3CuQ4u4P1rw/XcyzgLp2Aku7lI6waA1S7B9BFOpQwKyaho9oabVmurTqLWf0eXxemklZskZ2kBFPM0jP0-......U..U.................x.p....U..U.................3.1fc9bdc270429fa20PZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrH1KeS3CuQ4u4P1rw/XcyzgiI7p9y6Lbv2lzwUJxWzM96kcavlH4f0O206Ug9wDxr0=.an....U..U..............WA=...U..U..................Q.....U..U.................3.1f7999523619c1b0fPZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrEMvogScDF7HlUxg8PL+6kEFSeJWX5zoexl2+xqyc4q+52ImmB+2QokNliV3Z0xKcS2+FDD7CoX+maVSU6uu+SX..F....U..U.............3.18daa6bfa06b70c03PZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrH+Cke6uc2p1Ffl2AYvLF2r7ngm4iiyI4XOoMcDODAPoiEA7LmOkCK66N6cb80iql2E6CfiCza+ivc2mlfUf/R6.......U..U.................x.p....U..U.................3.1827be0aa4d4fe1c1PZq9YjgtkdqtS8Iw4vKCwi7AJ2Vr3dvbNaio1F9WYrExYLyT9xR3tTqTGAN2CNEnnDaemapmVsqahVhvk7lmTcDtRNjY/DkG+XjLCooic0k=.&r....U

after using new app of tuya developer portel, I am unable to register the device, illegal client id

root@openhab:/etc/openhab2/scripts/njsTuya/scripts# tuya-cli link-wizard
? Make the indicator light on your device flash.
For most devices, this means holding down the main button.
Press return when it's blinking. Yes
? What's your WiFi called? NETGEAR05
? What's the password for your WiFi? [hidden]
? How many devices do you want to link? 1
? Do you want to save devices that are successfully linked? Yes
โœ– Device(s) failed to be registered!
{ code: 'ILLEGAL_CLIENT_ID', message: 'Illegal clientId' }

Typo and intermittent failures from last merge

It looks like there might be a typo at (line 356):

client.on('error', err => {
    error(e);
});

e should actually be err.

I'm also seeing failure with this merge to consistently control my switches where the previous version had no issues. I do not believe the above typo is the cause, but I did find it because of the failure to set state. It could be messing with my retry logic however.

Connection blocked

Sometimes the application shows the error:
"Error communicating with device. Make sure nothing else is trying to control it or connected to it."

And I only use one instance of the software. I tried to restart de application, but nothing.
There is any way to see the blocked connections, o do something?

npm WARN enoent ENOENT: no such file or directory 'package.json'

#17 Hey guys.
I'm trying to install the package as mentioned in the FAQ:
npm install codetheweb/tuyapi
Which returns

npm WARN enoent ENOENT: no such file or directory, open '/home/openhabian/package.jsonโ€™
npm WARN openhabian No description
npm WARN openhabian No repository field.
npm WARN openhabian No README data
npm WARN openhabian No license field.

I don't know how to resolve this

Unexpected token ๏ฟฝ in JSON at position 56

Hey guys,

Running NodeJS version 6.12.2 on Ubuntu 16.04. Installed tuyapi per npm instructions and setup a test file with per the Readme page: getStatus, setStatus, then another getStatus.

When I run the file I have the connected lamp turned on. I'm also making sure I'm out of any TuyaSmart apps on the the phone/tablet.

The first getStatus function returns a Status: true message.
The next setStatus function does turn off the lamp and returns a Result of setting status false: true message.
The next message this is displayed in the console is:

SyntaxError: Unexpected token ๏ฟฝ in JSON at position 56
    at Object.parse (native)
    at _send.then.err (/home/utladmin/node/tuyapi/node_modules/tuyapi/index.js:64:19)
    at process._tickCallback (internal/process/next_tick.js:109:7)

I would think maybe something could be wrong with the id, uid or key for the outlet, but the fact that it can turn lamp off makes me think these variables are correct.

Any thoughts/help would be very much appreciated. Thanks,

Error when attempting to link

Hi,

I am unable to link successfully using either tuyapi-cli link-wizard or by using the sample dev.js script code shown at https://github.com/TuyaAPI/link.

I did have to add 255.255.255.255 broadcasthost to my hosts file to get past the first error, but I consistently arrive at the error:

- Registering devices(s)...
ร— Device(s) failed to be registered!
Error: Timed out wating for device(s) to connect to cloud
    at Promise (...\@tuyapi\cli\node_modules\@tuyapi\cloud\index.js:275:12)
    at <anonymous>

I am seeing consistent results on two different computers (Windows 10 running Cygwin and Mac running OSX) and with two different devices.

Does the brand of the devices (smart plugs) matter? They both link successfully using the Tuya android apps.

Any suggestions?

Thanks,
Don

dps=1 is hardcoded in index.js

This only affects devices with more than one channel so is not a high priority.

Adding an if clause like the following to index.js around line 190 will fix it:

      if (options.dps !== undefined) {
          resolve(data.dps[options.dps]);
      }
      else {
          resolve(data.dps['1']);
      }

Thanks!

Error with tuya-cli link-wizard

Hey, thanks for your fantastic work.
I get an error using tuya-cli
I have no problems adding the plug with this app https://play.google.com/store/apps/details?id=com.tuya.smartlife&hl=de

โœ– Device(s) failed to be registered! { Error: getaddrinfo EAI_AGAIN at Object._errnoException (util.js:1022:11) at errnoException (dns.js:55:15) at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26) code: 'EAI_AGAIN', errno: 'EAI_AGAIN', syscall: 'getaddrinfo', hostname: 'broadcasthost' }

Error: resolveIds() timed out

Hi, the script was running fine for a few months, and now I got this issue surfaced in the last few weeks. I can confirm that the uuid and localkey are correct and freshly retrieved.
I'm using tuyapi v2.0.3.
Could you please help? Thanks!

(node:4890) UnhandledPromiseRejectionWarning: Error: resolveIds() timed out. Is the device ID correct and is the device powered on?
at timeout (/home/nvidia/mining_monitor/node_modules/tuyapi/index.js:129:11)
at Timeout.setTimeout [as _onTimeout] (/home/nvidia/mining_monitor/node_modules/p-timeout/index.js:19:13)
at ontimeout (timers.js:458:11)
at tryOnTimeout (timers.js:296:5)
at Timer.listOnTimeout (timers.js:259:5)
(node:4890) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:4890) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Getting an AES error

Hey guys,

I'm not able to get it running. It throws the following error:

/node_modules/node-forge/lib/aes.js:203
    var len = tmp.length();
                  ^

TypeError: tmp.length is not a function
    at forge.aes.Algorithm.initialize (/node_modules/node-forge/lib/aes.js:203:19)
    at new forge.cipher.BlockCipher (/node_modules/node-forge/lib/cipher.js:118:18)
    at Object.forge.cipher.createCipher (/node_modules/node-forge/lib/cipher.js:42:10)
    at new TuyaCipher (/node_modules/tuyapi/lib/cipher.js:13:30)
    at new TuyaDevice (/node_modules/tuyapi/index.js:42:24)
    at /app.js:28:13
    at Array.forEach (native)
    at initDevices (/app.js:26:18)
    at Object.<anonymous> (/app.js:36:1)
    at Module._compile (module.js:577:32)

Any ideas?

error while using link-wizard and trying to obtain local-key

Okay, the issue is something I'm not sure of but its some socket error so I'm pasting the callback

"minichota@Matthew:/mnt/c/Windows/System32$ sudo tuya-cli link-wizard
? Make the indicator light on your device flash.
For most devices, this means holding down the main button.
Press return when it's blinking. Yes
? What's your WiFi called? something-.-
? What's the password for your WiFi? [hidden]
? How many devices do you want to link? 1
? Do you want to save devices that are successfully linked? Yes
โ น Registering devices(s)...events.js:183
throw er; // Unhandled 'error' event
^

Error [ERR_SOCKET_CANNOT_SEND]: Unable to send data
at Socket.onListenError (dgram.js:362:22)
at Object.onceWrapper (events.js:315:30)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at _handle.lookup (dgram.js:267:14)
at _combinedTickCallback (internal/process/next_tick.js:141:11)"
I'm on windows and I'm not sure, I'm using bash to run this, can someone please explain

Infinite loop in TuyaDevice.prototype._extractJSON function

If the message contains more open braces "{" than close braces "}" the function goes into an infinite loop.

The real fix would be to clean up the decrypted message to remove the invalid brace at the end. I have seen similar characters at the end of messages when using zero padding in AES (not 100% sure this is the issue.) I cleaned up my messages by switching to PKCS7 padding.

A quick fix is to check for the number of close braces before entering the loop

    var leftBrackets = stringOccurrence(data, '{');
    var rightBrackets = stringOccurrence(data, '}');
    if (leftBrackets > rightBrackets) { leftBrackets = rightBrackets }

but this could end up with bad returned JSON if there happens to be other invalid '{' and '}' characters

Registering a device

Some discussion on #5 are about figuring out the registration process, I'm starting a thread here so we can focus on this particular issue.

I recorded with fiddler on my old phone the action of adding a new device to the SmartLife App. I also recorded with WireShark all the UDP packets sent by either the device I was registering or the phone I was using to register the device.

I will try to make something readable of all of this and post all the info here, i will just need a little time.

My conclusion from a quick glance a the data:

  • During the process, the phone is making a constant repeated request to the SmartLifeAPI, while sending on the network in a loop a sequence of 4 UDP packets. (143 times)
  • At some point, it changes he UDP loop. The phone starts sending a bunch of UDP packets ( a sequence of 64 different packets) in a loop. (30 times), while some other requests are made to the SmartLifeAPI

So my guess is:

  • The lost devices (with no connection to anything) are constantly listening and interested about protocol ABCDXYZ
  • The first 4 UDP packets are something like "Hey, somebody listening? I got something to say about protocol ABCDXYZ!!!" So the device will get interested to what the phone has to say
  • The second UDP sequence of 64 packets are the info, and I guess it contains at least: Wifi Information + SmartLifeApi information
  • When the device got all the info, he then contact the SmartLifeAPI and register itself.
  • During this time, the phone is constantly poking the SmartLifeAPI to know if the device has been registered yet. Then when it does, the app goes to 100% and asks you some info.

That's how i imagine the registration works.

How to construct

Hello @codetheweb,

Thank you for your awesome code. Im a completely noob (I'm a humble MD student trying to make my home smart on a budget) and I'm having a hard time figuring out how to use all the information here to get my outlet to work with Homebridge. For example, I'm able to get all the parameters

ip: 'xxx.yyy.0.zzz', (The IP on the tuya server and the local IP on my router)
id: 'xxxxxxxxxxxxxxxxxxxx',
uid: 'xxxxxxxxxxxxxxxxxxxx',
key: 'xxxxxxxxxxxxxxxx'});

but I have no Idea what to do with them, what file I have to create (if any) or in which file do I have to put them to make it work. Could you please direct me on the right track, or provide me with some links to read and learn how I can make it work?

I would really appreciate any help, and sorry for any inconvenience.

Common/Consistent API behaviour

Issue: It seems like every update not just the major 2.0 breaks my wrapper. Rather than just bitching I was wondering if it's worth considering a more elegant solution.

Is there an API or generic setup so heating functions have universal names and behaviour. I'm not sure if NEST/HIVE have a nice API.

How easy is it to switch between the various ports?
https://github.com/codetheweb/tuyapi
python-tuya a Python port by clach04 https://github.com/clach04/python-tuya
m4rcus.TuyaCore a .NET port by Marcus-L https://github.com/Marcus-L/m4rcus.TuyaCore

It would be quite nice if there was a way to easily switch the backend system between the various ports. This might not be an issues as such so maybe you guys just need to give me a reading list and close this ticket.

Setup instructions are missing a step

Just a quick note to say I think the setup instructions are missing a step. In Charles I had to explicitly allow SSL connections from all hosts. I can post a screenshot when I am back at the machine I did it on, but from memory it was in preferences and I just allowed a * wildcard.

Without this, Charles only sees some connections and not the ones required to get the ID and details.

Device(s) Failed to be registered!

I've created the Tuya account and obtained the ID and Key from the site.

When I go to add a device I get the following error.
Device(s) failed to be registered!
Error: Timed out wating for device(s) to connect to cloud
at Promise (/usr/local/lib/node_modules/@tuyapi/cli/node_modules/@tuyapi/cloud/index.js:275:12)
at

the wizard is on a Docker environment with oznu homebridge and its homebridge-config-ui-x installed via its homebridge-syno-spk package on my nas synology ds218+

I'm using this smart plug "https://www.amazon.fr/gp/product/B07BKY4QFV/ref=oh_aui_detailpage_o07_s00?ie=UTF8&psc=1" with the Smart Life app.

I put the switch in pairing mode but the wizard never finds it. Instantly can add it back to the Smart Life app though.

I use the iOS APP KEY from Tuya for apikey in the wizard and iOS APP Secret from Tuya for apisecret in the wizard. Am I doing something wrong?

I am French and quite bad in English, excuse me in advance for errors in pronunciation, spelling, grammar and especially comprehension.

How can I remove saved key / secret key

The first time I tried the link-wizard I said yes remember key, however it did not work with the same results as the other open failed to register issue. I was not sure if I had added the correct secret key so wish to try again. How do I un-save the keys?

General Discussion

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!

Set up steps

Hello, I asked this question before but I didn't get any reply. I have installed homebridge-tuya-outlet, and I found the DevID but u don't know how to found the local key. Also, can you tell me what's the full steps that can put tuya into HomeKit?Thanks so much.

Scheduling Goldair Wifi controllable Heaters using tuyapi

Firstly, I love the work you have done with the tuyapi library.

I am using tuyapi library with these Goldair Wifi controllable heaters http://www.goldair.co.nz/product-catalogue/heating/panel-heaters which I found use the Tuya IOT framework. The mobile app annoyingly does not have a schedule feature - only a simple timer you have to set every day. I have implemented my own schedule using crontab running on a Raspberry Pi.

Here are some notes on how I got this working.

Device Encryption Key discovery is done by finding these in the mobile app log file.

Heater Settings

'1': true, -on/off
'2': 14, -setpoint
'3': 19, -current Temp, readonly
'4': 'C', - 'C' comfort, 'ECO', 'AF' AntiFreeze
'6': false, -child lock on
'12': 0, -fault, readonly
'101': 'stop', -power level 'stop','1','2','3','4','5','auto'
'102': 1440, -timer in mins
'103': false, -timer on
'104': true, -led display on
'105': 'auto', -mode 'auto', 'user' - what is the difference?
'106': 14 -eco temp set point between 5-31

Code snippet of scheduling (crontab calls this with a scene param)

 if (scene == 'evening'){
            //evening 18 deg, on, LED on
            tuya.set({id: Heater1Id, dpscommand:'{"1":true,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater1Id was changed')); 
            tuya.set({id: Heater2Id, dpscommand:'{"1":true,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater2Id was changed')); 
            tuya.set({id: Heater3Id, dpscommand:'{"1":true,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater3Id was changed')); 
        }

        if (scene == 'night'){
            //night 18 deg, locked, LED off
            tuya.set({id: Heater1Id, dpscommand:'{"1":true,"2":18,"6":true,"104":false}'}).then(() => console.log('Heater1Id was changed')); 
            tuya.set({id: Heater2Id, dpscommand:'{"1":true,"2":18,"6":true,"104":false}'}).then(() => console.log('Heater2Id was changed')); 
            tuya.set({id: Heater3Id, dpscommand:'{"1":true,"2":18,"6":true,"104":false}'}).then(() => console.log('Heater3Id was changed')); 
        }

        if (scene == 'morning'){
            //morning 7am, turn off, LED on, locked
            tuya.set({id: Heater1Id, dpscommand:'{"1":false,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater1Id was changed')); 
            tuya.set({id: Heater2Id, dpscommand:'{"1":false,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater2Id was changed')); 
            tuya.set({id: Heater3Id, dpscommand:'{"1":false,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater3Id was changed')); 
        }

Extension to device set method to allow multiple settings to be changed at one time

/*
* @param {Object} options - options for setting properties
* @param {String} [options.id] - ID of device
* @param {Boolean} options.set - `true` for on, `false` for off
* @param {Number} [options.dps] - dps index to change
* @param {String} [options.dpscommand] - dps command string
*/
...
  if (options.dpscommand !== undefined) {
    thisRequest.dps = JSON.parse(options.dpscommand)
  }

I hope this helps.

ENOTFOUND Error - broadcasthost ip

Describe the bug
A clear and concise description of what the bug is.
I believe I have a similar problem as described in issue #54
Unfortunately I have no idea which IP adress to put into for

 broadcasthost ip

Additional context
I am not sure if my socket can actually be registered with your API,...
it works fine with the Smart Life ios App.
The machine I use above is a linux Mint machine

this is my output on the console
xxx@xxx ~ $ tuya-cli link-wizard
? Make the indicator light on your device flash.
For most devices, this means holding down the main button.
Press return when it's blinking. Yes
? What's your WiFi called? XXXXXXX
? What's the password for your WiFi? [hidden]
? How many devices do you want to link? 1
? Do you want to save devices that are successfully linked? Yes
โœ– Device(s) failed to be registered!
{ Error: getaddrinfo ENOTFOUND broadcasthost
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:50:26)
errno: 'ENOTFOUND',
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'broadcasthost' }

Support for Multiple DataPoints (e.g. for wall switches)

Hi !
Thanks for that grat project. Makes my new wall switch works together with my smarthome.
I bought a Xenon / Jinvoo (Tuya based) Wall switch with two buttons.
Like this one: https://de.aliexpress.com/item/Manufacturer-Xenon-Wall-Switch-110-240V-Smart-Wi-Fi-Switch-button-Glass-Panel-3-gang-Ivory/32774600013.html

I first tried to flash it with tasmota FW, without success. So after hours of research, i found this project. After some small code changes , i successfully integrate the switch into my smarthome environment (iobroker mainly).

Only problem with the tuyapi was, that it only supports one datapoint (Means one button). So i add that functionality to the getStatus and setStatus method. I like to share my changes here, maybe someone also has that requirement. I just tested it with my wall switch! Works fine for me.

`
/**

  • Gets the device's current status.

  • @param {function(error, result)} callback

  • @param {number} [dpId=1] - DataPoint for multi switch devices
    */
    TuyaDevice.prototype.getStatus = function (callback, dpId) {
    var dpId = dpId || 1;

    // Add data to command
    if ('gwId' in requests[this.type].status.command) {
    requests[this.type].status.command.gwId = this.id;
    }
    if ('devId' in requests[this.type].status.command) {
    requests[this.type].status.command.devId = this.id;
    }

    // Create byte buffer from hex data
    const thisData = Buffer.from(JSON.stringify(requests[this.type].status.command));
    const buffer = this._constructBuffer(thisData, 'status');

    this._send(buffer).then(data => {
    // Extract returned JSON
    try {
    data = data.toString();
    data = data.slice(data.indexOf('{'), data.lastIndexOf('}') + 1);
    data = JSON.parse(data);
    return callback(null, data.dps[dpId]);
    } catch (err) {
    return callback(err, null);
    }
    });
    };

/**

  • Sets the device's status.

  • @param {boolean} on - true for on, false for off

  • @param {function(error, result)} callback - returns true if the command succeeded

  • @param {number} [dpId=1] - DataPoint for multi switch devices
    */
    TuyaDevice.prototype.setStatus = function (on, callback, dpId) {
    const thisRequest = requests[this.type][on ? 'on' : 'off'];
    var dpId = dpId || 1;

    // Add data to command
    const now = new Date();
    if ('gwId' in thisRequest.command) {
    thisRequest.command.gwId = this.id;
    }
    if ('devId' in thisRequest.command) {
    thisRequest.command.devId = this.id;
    }
    if ('uid' in thisRequest.command) {
    thisRequest.command.uid = this.uid;
    }
    if ('dps' in thisRequest.command) {
    thisRequest.command.dps = JSON.parse("{""+dpId+"": "+on+"}");
    }
    if ('t' in thisRequest.command) {
    thisRequest.command.t = (parseInt(now.getTime() / 1000, 10)).toString();
    }

    // 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 = this._constructBuffer(thisData, [on ? 'on' : 'off']);

    // Send request to change status
    this._send(buffer).then(data => {
    return callback(null, true);
    }).catch(err => {
    return callback(err, null);
    });
    };
    `

Cant Fetch Required Paramaters

Hello, Im having trouble using Charles to get the IDs , I followed the direction and signed ther certificatte on my iphone and everything but still just getting gibberish, the text doesnt display like your direction does.

https://gyazo.com/7f40922412ab92efe1004e7ff12933c8

Is there an easier way to pull the required IDs? Basically i'm trying to get the ID to implement into my own ios App to allow controlling of the switches I have.

TypeError: this is not a typed array

Running your example code from console in Ubuntu:

$ node ./tuya_test
/home/oriz/node_modules/tuyapi/index.js:55
const thisData = Buffer.from(JSON.stringify(requests[this.type].status.command));
^

TypeError: this is not a typed array.
at Function.from (native)
at TuyaDevice.getStatus.callback [as getStatus] (/home/oriz/node_modules/tuyapi/index.js:55:27)
at Object. (/home/oriz/tuya_test:10:6)
at Module._compile (module.js:410:26)
at Object.Module._extensions..js (module.js:417:10)
at Module.load (module.js:344:32)
at Function.Module._load (module.js:301:12)
at Function.Module.runMain (module.js:442:10)
at startup (node.js:136:18)
at node.js:966:3

Please advise?

npm i @tuyapi/cli -g is throwing error of permission denied

[13:56:33] root@smarthome:~/node_modules/cli-master# npm i @tuyapi/cli -g
(node:17491) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
npm ERR! git clone [email protected]:tuyapi/cli Cloning into bare repository '/root/.npm/_git-remotes/git-github-com-tuyapi-cli-3083bead'...
npm ERR! git clone [email protected]:tuyapi/cli Warning: Permanently added the RSA host key for IP address '192.30.253.112' to the list of known hosts.
npm ERR! git clone [email protected]:tuyapi/cli Permission denied (publickey).
npm ERR! git clone [email protected]:tuyapi/cli fatal: Could not read from remote repository.
npm ERR! git clone [email protected]:tuyapi/cli
npm ERR! git clone [email protected]:tuyapi/cli Please make sure you have the correct access rights
npm ERR! git clone [email protected]:tuyapi/cli and the repository exists.
npm ERR! addLocal Could not install tuyapi/cli
npm ERR! Error: ENOENT: no such file or directory, stat 'tuyapi/cli'
npm ERR! If you need help, you may report this entire log,
npm ERR! including the npm and node versions, at:
npm ERR! http://github.com/npm/npm/issues

npm ERR! System Linux 4.14.52-v7+
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "i" "@tuyapi/cli" "-g"
npm ERR! cwd /root/node_modules/cli-master
npm ERR! node -v v8.11.1
npm ERR! npm -v 1.4.21
npm ERR! path tuyapi/cli
npm ERR! syscall stat
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /root/node_modules/cli-master/npm-debug.log
npm ERR! not ok code 0
[14:07:44] root@smarthome:~/node_modules/cli-master#

Not really a issue: How to get IP address

How to get the ip address of my light bulb (geeni) that the internet says is a tuya?:
I tried to look on my routers setup tool however i do not see any thing that looks like my bulb
Thanks

toString causing issues, please use toString()

thisRequest.dps[options.dps.toString] = options.set;

Seems to be missing the () behind toString. This caused issues setting dps values with using this package from homebridge.

For example:

tuya.set({id: 'xxxxxxxxxxxxxxxxxxxx', 'dps': 2, set: true}).then(() => console.log('device was changed'))

Would fail because toString is not a function in prototype.

Proposed change:

thisRequest.dps[options.dps.toString()] = options.set;

or even:

if (options.dps === undefined) {
thisRequest.dps = {1: options.set};
} else {
thisRequest.dps = {};
thisRequest.dps[options.dps] = options.set;
}

tuyapi/index.js

Line 233 in 290d6e9

thisRequest.dps[options.dps.toString] = options.set;

Controlling Tuya devices with cloud API instead of controlling them locally

hi there,

First thank you for your valuable contributions to the tuya library. I realize this is a long shot, but i am wondering if anyone had success in calling the tuya cloud API? i used fiddler and i was able to decipher a lot of the information on the calls, but there is one thing missing.

How is tuya calculating the MD5 hash? I was not able to replicate their "sign" parameter to the URL and the details on this as slim. Most of the info is located at https://docs.tuya.com/en/cloudapi/cloud_access.html#access-mode (search for accesskey) but i could not get it to work following the example. (I had to order my parameters, i used localKey as the accessKey, and then i did a utf-8 encoded MD5 hash). For the time, i got it in seconds using Unix epoch time.

Once i complete my work, i will share the PowerShell script that can be replicated into standard http/json requests.

Idea: Emulate tuya device with tuyapi

I just thought if maybe it is possible/and or a good idea to emulate a tuya device with tuyapi.
So you can listen on port 6668 and get the messages from a local running app like Smart life.
So, you remove your hardware plug to make it inactive, then start an emulation on your PC with the known ID and localKey.

Setup using CLI-Wizard is throwing an error

This work is most impressive. Unfortunately for me I'm having an issue with the SETUP process. I got my API Key and Secret from tuya. Then I attempted the CLI WIZARD steps provided. My wifi password is a 10 digit string and as a result, I believe it is failing a password validity check. This is the error message I get.

[21:51:50] openhabian@openHABianPi:/etc/openhab2/scripts$ tuya-cli link-wizard
? Make the indicator light on your device flash.
For most devices, this means holding down the main button.
Press return when it's blinking. Yes
? What's your WiFi called? skittles
? What's the password for your WiFi? [hidden]
? How many devices do you want to link? 1
? Do you want to save devices that are successfully linked? Yes
โœ– Device(s) failed to be registered!
Error: Invalid WiFi password
at TuyaLink.registerSmartLink (/usr/lib/node_modules/@tuyapi/cli/node_modules/@tuyapi/link/lib/link.js:64:11)
at TuyaLinkWizard.linkDevice (/usr/lib/node_modules/@tuyapi/cli/node_modules/@tuyapi/link/index.js:93:23)
at
at process._tickCallback (internal/process/next_tick.js:188:7)

Frequent errors

I'm getting the following quite frequently, using the basic toggle example provided. I've tried to figure out what is going on but I simply don't get js and how it works.

(node:6521) 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. (node:6521) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

edit:
unparagoned/njsTuya#1

Mostly the toggle works but getting the state afterword is a problem.
What I've done is just rework myscript so it doesn't ask for the state again and it seems to be working fine. I just add some code around it and assume if a return result is true then it's changed state, rather than performing a second get call.

Edit: I get the errors now and then with the modified code but it's much less frequent.

install failure

C:\tmp>npm install @codetheweb/tuyapi
npm ERR! code E404
npm ERR! 404 Not Found: @codetheweb/tuyapi@latest

npm ERR! A complete log of this run can be found in:
npm ERR!     ......2017-11-30T02_11_55_438Z-debug.log

where 2017-11-30T02_11_55_438Z-debug.log contains:

0 info it worked if it ends with ok
1 verbose cli [ 'C:\\Program Files\\nodejs\\node.exe',
1 verbose cli   'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli   'install',
1 verbose cli   '@codetheweb/tuyapi' ]
2 info using [email protected]
3 info using [email protected]
4 verbose npm-session c8ac1559b4c1c76e
5 silly install loadCurrentTree
6 silly install readLocalPackageData
7 http fetch GET 404 https://registry.npmjs.org/@codetheweb%2ftuyapi 339ms
8 silly fetchPackageMetaData error for @codetheweb/tuyapi@latest 404 Not Found: @codetheweb/tuyapi@latest
9 verbose stack Error: 404 Not Found: @codetheweb/tuyapi@latest
9 verbose stack     at fetch.then.res (C:\Program Files\nodejs\node_modules\npm\node_modules\pacote\lib\fetchers\registry\fetch.js:42:19)
9 verbose stack     at tryCatcher (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\util.js:16:23)
9 verbose stack     at Promise._settlePromiseFromHandler (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\promise.js:512:31)
9 verbose stack     at Promise._settlePromise (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\promise.js:569:18)
9 verbose stack     at Promise._settlePromise0 (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\promise.js:614:10)
9 verbose stack     at Promise._settlePromises (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\promise.js:693:18)
9 verbose stack     at Async._drainQueue (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\async.js:133:16)
9 verbose stack     at Async._drainQueues (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\async.js:143:10)
9 verbose stack     at Immediate.Async.drainQueues (C:\Program Files\nodejs\node_modules\npm\node_modules\bluebird\js\release\async.js:17:14)
9 verbose stack     at runCallback (timers.js:789:20)
9 verbose stack     at tryOnImmediate (timers.js:751:5)
9 verbose stack     at processImmediate [as _immediateCallback] (timers.js:722:5)
10 verbose cwd C:\tmp
11 verbose Windows_NT 10.0.14393
12 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "@codetheweb/tuyapi"
13 verbose node v8.9.1
14 verbose npm  v5.5.1
15 error code E404
16 error 404 Not Found: @codetheweb/tuyapi@latest
17 verbose exit [ 1, true ]

resolveIds() never returns

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.