Skip to content

Instantly share code, notes, and snippets.

@shoeper
Forked from bahorn/tuya_cloud.py
Created June 14, 2018 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shoeper/52cd569ce2d4a26a0a7158ed5a064d0f to your computer and use it in GitHub Desktop.
Save shoeper/52cd569ce2d4a26a0a7158ed5a064d0f to your computer and use it in GitHub Desktop.
Cloud endpoint
import requests
import hashlib
import time
import uuid
import os
import copy
import json
# Fixed up version of my previous code to work with the Cloud endpoints.
# Hopefully this works.
# Had a quick look at their public cloud API implementation at:
# https://github.com/TuyaInc/TuyaDemo/
# to fix the issue.
## Use the region your device is registered in.
host = "https://a1.tuyaeu.com/api.json"
# Random and not really checked. Should keep persistent if you are using
# sessions.
device_id = os.urandom(32).encode('hex')
sid = ""
# Needs to be set, but they don't care what it is.
os = ("Linux", "0.1.2", "TEST")
# Your API keys.
appKey = "<BLANKED>"
appSecret = "<BLANKED>"
# This is the implementation of "sign".
def generate_request_sign(pairs):
# This are the values that get "signed" in a request, worth checking if I
# missed one in this list.
values_to_hash = ["a", "v", "lat", "lon", "lang", "deviceId", "imei",
"imsi", "appVersion", "ttid", "isH5", "h5Token", "os",
"clientId", "postData", "time", "n4h5", "sid", "sp"]
out = []
sorted_pairs = sorted(pairs)
for item in sorted_pairs:
if item not in values_to_hash:
continue
if pairs[item] == "":
continue
out += [item + "=" + str(pairs[item])]
sign_request = appSecret+"|".join(out)
h = hashlib.md5()
h.update(sign_request)
return h.hexdigest()
# This will give you a dict with all the request parameters.
def url_generator(action, version, post_data=None, sid=None, time_param=None):
client_id = appKey
lang = "zh-Hans"
if not time_param:
time_param = int(time.time())
request_id = uuid.uuid4()
pairs = {
"a": action,
"deviceId": device_id,
"os": os[0],
"v": version,
"clientId": client_id,
"lang": lang,
#"requestId": request_id,
"time": time_param,
}
if sid:
pairs['sid'] = sid
if post_data:
pairs['postData'] = post_data
pairs['sign'] = generate_request_sign(pairs)
return pairs
# Call the endpoint.
# * action is the name as defined in the tuya docs
# * version is the version they say to provide, normally "1.0"
# * data is the JSON data you want to pass to the action
# * requires_sid means it adds a session_id to the parameters. Used in mobile endpoints.
def preform_action(action, version, data=None, requires_sid=False):
if requires_sid is True and not sid:
return None
params = url_generator(action, version, data, sid)
print params
endpoint = host
headers = {
# Maybe set a user agent or something here.
}
if data:
r = requests.post(endpoint, params=params,
headers=headers)
else:
r = requests.post(endpoint, params=params, headers=headers)
return r.status_code, r.json(), r.headers
if __name__ == "__main__":
deviceID = "<DEVICE_ID_HERE>"
print preform_action("tuya.p.weather.city.info.list", "1.0",
json.dumps({"countryCode":"CN"}))
print preform_action("tuya.cloud.device.get", "1.0",
json.dumps({"devId": deviceID}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment