tuya-cloudcutter
A tool that disconnects Tuya IoT devices from the cloud, allowing them to run completely locally.
import os.path
import sys
import extract
import generate_profile_classic
import haxomatic
import process_app
import process_storage
import pull_schema
def print_filename_instructions():
print('Encrypted bin name must be in the pattern of Manufacturer-Name_Model-and-device-description')
print('Use dashes in places of spaces, and if a dash (-) is present, replace it with 3 dashes (---)')
print('There should only be 1 underscore in the filename, separating manufacturer name and model description')
if __name__ == '__main__':
if not sys.argv[1:]:
print('Usage: python build_profile.py <full 2M encrypted bin file> <token=\'None\'>')
print('Token is optional. Token instructions will prompt if needed.')
print_filename_instructions()
sys.exit(1)
token = None
if len(sys.argv) > 2 and sys.argv[2] is not None:
token = sys.argv[2]
file = sys.argv[1]
output_dir = file.replace('.bin', '')
base_name = os.path.basename(output_dir)
dirname = os.path.dirname(file)
storage_file = os.path.join(dirname, base_name, base_name + '_storage.json')
app_file = os.path.join(dirname, base_name, base_name + '_app_1.00_decrypted.bin')
schema_id_file = os.path.join(dirname, base_name, base_name + '_schema_id.txt')
extracted_location = os.path.join(dirname, base_name)
if base_name.count('_') != 1 or base_name.count(' ') > 0:
print_filename_instructions()
sys.exit(2)
print(f"[+] Processing {file=} as {base_name}")
extract.run(file)
haxomatic.run(app_file)
process_storage.run(storage_file)
process_app.run(app_file)
if not os.path.exists(schema_id_file):
pull_schema.run_directory(extracted_location, token)
else:
print('[+] Schema already present')
if not os.path.exists(schema_id_file):
print("[!] Unable to build complete profile as schema remains missing.")
exit(1)
generate_profile_classic.run(extracted_location)