-
Notifications
You must be signed in to change notification settings - Fork 54
Setup
This is a snapshot of the https://github.com/codetheweb/tuyapi/ readme from the 2018-01-31 https://raw.githubusercontent.com/codetheweb/tuyapi/9c835da1139a3436f43b359b86abeb3529ae90a1/docs/SETUP.md
- Download Charles.
- Turn off the local proxy for your computer:
- And turn off recording for now (with the red button), so it's easier to find the correct data later on:
-
Setup Charles' SSL certificate for your phone. If the app throws network errors, you may have to take an additional step to fully trust the Charles SSL certificate:
Settings > General > About > Certificate Trust Testings
-
Proxy your phone's traffic through Charles (IP is the IP of your computer):
- Launch the app that came with your device. If you've already added the device you want to configure to the app, remove it now.
- Add your device. Before tapping "Continue" after entering your network's password, pause and turn back on traffic recording in Charles.
- When the device is added in the app, turn off traffic recording in Charles.
- Find the HTTPS request where
a=s.m.dev.list
:
- Find the parameters needed for constructing a TuyAPI instance from the contents of the response:
{
id: uuid,
uid: productId,
key: localKey
}
Only requires an Android device. Root not required, this captures the stream from the Android application to the Jinvoo/Tuya web servers. It does NOT capture between Android device and remote control device.
-
Remove registration for existing device if present
-
Install "Packet Capture" https://play.google.com/store/apps/details?id=app.greyshirts.sslcapture (follow instructions, install cert, then start capturing, its possibly to use the green triangle/play button with a "1" on it to only capture from the Jinvoo app).
-
Run Jinvoo Smart App (https://play.google.com/store/apps/details?id=com.xenon.jinvoo version 1.0.3 known to work) to (re-)add device.
-
Hit stop button back in "Packet Capture" app.
-
review captured packets (first or last large one, 9Kb of 16Kb) use macOS step 11 for guide.
From https://github.com/codetheweb/tuyapi/issues/5#issuecomment-352932467
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.
Note that this has changed in the latest version of the app. The data is now stored in the same directory but the file is called preferences_global_key<someid>.xml.
TIP: Look for the file with the largest size. The actual data can be found in <map><string>. Something akin to a small script to parse it in node js:
const fs = require('fs');
const path = require('path');
const xml2js = require('xml2js');
const data = fs.readFileSync(path.join(__dirname, process.argv[2]), {encoding: 'UTF-8'});
xml2js.parseString(data, function (err, result) {
console.dir(result.map.string);
});
node decode.js preferences_global_key\<someid\>.xml
A more detailed script to decode and write to a separate devices.json file can be found here
The Jinvoo SMart app is similar to the Smart Life app but has a slightly different location. /data/data/com.xenon.jinvoo/shared_prefs/gw_storage.xml
. Python script to dump out the information along with useful schema information:
#!/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))