Install TuyAPI
masterInstall the library via npm to communicate with Tuya cloud network devices.
npm install codetheweb/tuyapirepository·master·Indexed 25 days ago
https://github.com/codetheweb/tuyapiA library for communicating with Tuya cloud network devices, allowing developers to control and monitor smart devices that use the TuyaSmart app or have port 6668 open. It supports both asynchronous event-based and synchronous async/await flows, and provides tools for handling protocol 3.3 and manual device refreshes. The package includes a CLI tool (@tuyapi/cli) to help retrieve device IDs and keys via the Tuya IoT platform or network sniffing.
Install the library via npm to communicate with Tuya cloud network devices.
npm install codetheweb/tuyapiBefore you can link devices or list them, you must install the @tuyapi/cli tool globally via npm.
npm i @tuyapi/cli -gIf you encounter permission errors, you may need to prefix the command with sudo.
To construct a TuyAPI instance, you need three specific parameters: id (uuid), uid (productId), and key (localKey). You can intercept the HTTPS traffic from your device's official app using Charles Proxy on macOS to find these values.
Settings > General > About > Certificate Trust Settings to fully trust it.a=s.m.dev.list is present.id: uuiduid: productIdkey: localKey{
id: uuid,
uid: productId,
key: localKey
}If you have a rooted Android device, you can bypass network sniffing by reading the app's shared preferences directly.
Locate the settings at:
/data/data/com.tuya.smartlife/shared_prefs/dev_data_storage.xml
Inside this file, look for the tuya_data string. This string is HTML entity encoded; you must decode it to reveal a JSON string containing your device keys.
Locate the settings at:
/data/data/com.xenon.jinvoo/shared_prefs/gw_storage.xml
You can use a Python script to parse this XML and extract the device metadata, including localKey, uuid, and the device schema.
#!/usr/bin/env python
# -*- coding: us-ascii -*-
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
#
import codecs
import os
import json
import xml.etree.ElementTree as ET
try:
# Python 2.6-2.7
from HTMLParser import HTMLParser
except ImportError:
# Python 3
from html.parser import HTMLParser ## FIXME use html.unescape()
xml_in_filename = 'com.xenon.jinvoo/shared_prefs/gw_storage.xml'
h = open(xml_in_filename, 'r')
xml = h.read()
h.close()
builder = ET.XMLTreeBuilder()
builder.feed(xml)
tree = builder.close()
h = HTMLParser()
for entry in tree.findall('string'):
if entry.get('name') == 'gw_dev':
# found it, need content
config = entry.text
s = h.unescape(config)
config_dict = json.loads(s)
#print(config_dict)
print(len(config_dict))
for device in config_dict:
#print(device)
for key in ['name', 'localKey', 'uuid', 'gwType', 'verSw', 'iconUrl']: # and/or 'gwId', 'devId'
print('%s = %r' % (key, device[key]))
# there is a bunch of interesting meta data about the device
print('schema =\')
schema = device['devices'][0]['schema'] # NOTE I've only seen single entries
schema = h.unescape(schema)
schema_dict = json.loads(schema)
print(json.dumps(schema_dict, indent=4))
print('')
print(json.dumps(config_dict, indent=4))You can use TuyAPI with async/await for a synchronous flow. This is useful for one-off commands or scripts where you want to wait for specific actions to complete before proceeding.
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();
})();This is the fastest method. It requires your devices to already be registered in the official Tuya Smart or Smart Life apps.
tuya-cli wizardSave the outputted information for use with TuyAPI.
The recommended way to use TuyAPI is through an asynchronous, event-based approach. This allows you to listen for connection changes, errors, and incoming data updates from the device.
Key events:
connected: Emitted when the connection to the device is established.disconnected: Emitted when the connection is lost.error: Emitted when an error occurs.data: Emitted when the device sends data updates. The data object contains a dps property with device parameters (e.g., data.dps['1']).dp-refresh: Emitted when a manual refresh is triggered on certain devices.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);If you are using an Android device, you can capture the traffic between the app and the Tuya/Jinvoo servers without rooting the device.
Use this method if you want to link devices regardless of whether they are currently in a Tuya app. This requires a developer account at iot.tuya.com.
IoT CoreAuthorizationSmart Home Scene Linkagecom.) and a Channel ID.schema value for the CLI command.tuya-cli link --api-key <your api key> --api-secret <your api secret> --schema <your schema/Channel ID> --ssid <your WiFi name> --password <your WiFi password> --region <us|eu|cn>Note: For --region, use the two-letter code (us, eu, or cn) geographically closest to you.
tuya-cli link --api-key <your api key> --api-secret <your api secret> --schema <your schema/Channel ID> --ssid <your WiFi name> --password <your WiFi password> --region usSome newer devices do not send data updates unless the official app is open. To receive updates from these devices, you must "force" them by calling refresh().
When using this method, you should listen for the dp-refresh event. You can also use the issueRefreshOnConnect: true option in the constructor to attempt this on connection.
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(() => {
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);The TuyaDevice class extends EventEmitter and emits several events during its lifecycle:
connected: Emitted when the socket connection is successfully established.disconnected: Emitted when the socket is closed or the device goes offline.data: Emitted when the device proactively sends data (e.g., a status update).(payload, commandByte, sequenceN)dp-refresh: Emitted when the device proactively returns updated DP values.(payload, commandByte, sequenceN)heartbeat: Emitted when a heartbeat pong is received from the device.error: Emitted on socket errors, connection timeouts, or parsing errors.error (string/Error): When nullPayloadOnJSONError is true, a string error might be emitted.Error: sign invalidOne of your credentials (api-key, api-secret, or schema) is incorrect. Re-verify these values from the Tuya IoT platform.
Device(s) failed to be registered! Error: Timed out waiting for devices to connect.The device failed to authenticate against the Tuya API. Try these steps: