{"id":13710587,"url":"https://github.com/jaqxues/TelloPython","last_synced_at":"2025-05-06T19:32:15.000Z","repository":{"id":224978898,"uuid":"229307259","full_name":"jaqxues/TelloPython","owner":"jaqxues","description":"Normal and reverse engineered (\"advanced\") Python Api for Tello","archived":false,"fork":false,"pushed_at":"2021-03-14T11:30:26.000Z","size":66,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-13T21:44:31.026Z","etag":null,"topics":["reverse-engineering","tello","tello-python3","tellodrone"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jaqxues.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-12-20T17:20:56.000Z","updated_at":"2024-05-04T10:19:22.000Z","dependencies_parsed_at":"2024-02-28T18:12:56.127Z","dependency_job_id":null,"html_url":"https://github.com/jaqxues/TelloPython","commit_stats":null,"previous_names":["jaqxues/tellopython"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaqxues%2FTelloPython","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaqxues%2FTelloPython/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaqxues%2FTelloPython/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaqxues%2FTelloPython/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaqxues","download_url":"https://codeload.github.com/jaqxues/TelloPython/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252753637,"owners_count":21798987,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["reverse-engineering","tello","tello-python3","tellodrone"],"created_at":"2024-08-02T23:00:58.631Z","updated_at":"2025-05-06T19:32:09.983Z","avatar_url":"https://github.com/jaqxues.png","language":"Python","funding_links":[],"categories":["SDK Wrappers"],"sub_categories":[],"readme":"# TelloPython\n*Allows to control your Tello Drone via Python.* \n\nIn addition to the \"official\" and documented APIs, TelloPython also supports also a number of reverse engineered \nfunction, such as \"Flip\", which are not in mentioned in the documentation, and only accessible through the App. Have a\nlook [demo.py](demo.py), a small script to control the drone with your keyboard, which is not possible with the \ndocumented APIs (using reverse engineered Joystick Controls).\n\nThis Readme also goes through the Basics of how the Tello App was reverse engineered and a basic breakdown on how the\napp works.\n\n# Introduction to reverse engineering\n\n## Basics\n* The Tello App does not send Strings (e. g. \"land\" or \"takeoff\" to the Drone). Instead it sends Command Ids to the \n  drone (shorts). To find the ids:\n* The `SocketPacketEntitiy` class contains different fields that you need to figure out before sending any command. To\n  log the values of the arguments, I used the Xposed Framework (though you can probably figure it out with Wireshark):\n    * cmdId: int\n    * data: byte[]\n    * pactype: int\n    * seqnum: short\n    * version: int\n\n## How to find these Command Ids etc\n* In the Tello App, the raw ids can be found in classes extending `com.ryzerobotics.tello.gcs.core.cmd.e`. (You can run\n  the scripts in `dev_utils.py` to find Command Ids used in comparisons. These script need a decompiled Tello Folder\n  (preferably from Jadx). A more complete list (still maybe not all ids) can be found in `cmd_ids`\n* You should be able to figure out some Commands by having a look at the class `com.ryzerobotics.tello.gcs.core.cmd.c`\n  (\"ZOCmdStore\")\n* By setting the Tello Application to `UserDebuggable` you can use the \"Android Layout Inspector\" and figure out the ids\n  of the buttons and search for their `onClickListener` (done to find `flip` command)\n* With Xposed, you can hook every method of the classes extending `e`. Check what Id gets sent when using different\n  features. (Takeoff, land etc.). A simpler way (less complete) would be hooking the before mentioned\"ZOCmdStore\" class.\n* Similarly, you can hook the constructor of the class `com.ryzerobotics.tello.gcs.core.c` (\"ZOCmdParser\") and log \n  the `cmdId` field of the result of method `com.ryzerobotics.tello.gcs.ui.bean.SocketPacketEntity a(byte[], int)`. \n  Note that the `byte[]` sometimes contains useful information in form of text.\n\n\n## Using different commands\n\n###  The Joystick command\nThe joystick is handled by `com.ryzerobotics.tello.gcs.core.cmd.d.a(int, int, long, long, long)`\nValues are set using Commands in \"ZOCmdSendManager\". Chinese names for the values are mentioned in log statements with \ntag \"yaogan\" - \"Joystick\"). You can understand their meaning by Trial and Error or hooking the Tello App and seeing\nwhat values are passed to the method when using the Joystick in app.\n\n| Chinese names | Directions                   | Name     |\n| ------------- |:-----------------------------| :--------|\n| zuoYou        | right - left                 | roll     |\n| qianHou       | forward - backward           | pitch    |\n| shangXia      | up - down                    | throttle |\n| xuanZhan      | clockwise - counterclockwise | yaw      |\n\nThe last `long` argument does not have a specific name. This `speed_mode` variable is either 0 (slow mode) or 1 (quick \nmode). The values of the other arguments are ints between 364 - 1684 (both included).\n\n* Min (movement on corresponding axis): 364\n* ...\n* Normal (no movement on corresponding axis): 1024\n* ...\n* Max (movement on corresponding axis): 1684\n\nSpeed per axis given by `abs(1024 - x)`. Direction on axis given by `x \u003e 1024`\n\n## The Flip command\nThe Flip command takes an int (0 \u003c= int \u003c= 7) to set the direction. 0, 1, 2, 3 are front-, left-, back-, right-flip\nrespectively. Values 4, 5, 6, 7 are for diagonal flips.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaqxues%2FTelloPython","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaqxues%2FTelloPython","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaqxues%2FTelloPython/lists"}