├── fq777 ├── dronejoystick.py ├── dronekeyboard.py ├── __init__.py ├── dronecontrol.py └── dronevideo.py ├── .gitignore └── LICENSE /fq777/dronejoystick.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fq777/dronekeyboard.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fq777/__init__.py: -------------------------------------------------------------------------------- 1 | from dronecontrol import DroneControl 2 | from dronevideo import DroneVideo 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ricardo Pascal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /fq777/dronecontrol.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import time 3 | 4 | 5 | HANDSHAKE_DATA = bytearray([0x49, 0x54, 0x64, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x81, 0x85, 0xFF, 0xBD, 0x2A, 0x29, 0x5C, 0xAD, 0x67, 0x82, 0x5C, 0x57, 0xBE, 0x41, 0x03, 0xF8, 0xCA, 0xE2, 0x64, 0x30, 0xA3, 0xC1, 6 | 0x5E, 0x40, 0xDE, 0x30, 0xF6, 0xD6, 0x95, 0xE0, 0x30, 0xB7, 0xC2, 0xE5, 0xB7, 0xD6, 0x5D, 0xA8, 0x65, 0x9E, 0xB2, 0xE2, 0xD5, 0xE0, 0xC2, 0xCB, 0x6C, 0x59, 0xCD, 0xCB, 0x66, 0x1E, 0x7E, 0x1E, 7 | 0xB0, 0xCE, 0x8E, 0xE8, 0xDF, 0x32, 0x45, 0x6F, 0xA8, 0x42, 0xEE, 0x2E, 0x09, 0xA3, 0x9B, 0xDD, 0x05, 0xC8, 0x30, 0xA2, 0x81, 0xC8, 0x2A, 0x9E, 0xDA, 0x7F, 0xD5, 0x86, 0x0E, 0xAF, 0xAB, 0xFE, 8 | 0xFA, 0x3C, 0x7E, 0x54, 0x4F, 0xF2, 0x8A, 0xD2, 0x93, 0xCD]) 9 | 10 | START_DRONE_DATA = bytearray([0xCC, 0x7F, 0x7F, 0x0, 0x7F, 0x0, 0x7F, 0x33]) 11 | 12 | 13 | class DroneControl(object): 14 | def __init__(self): 15 | self._ip = '172.16.10.1' 16 | self._tcp_port = 8888 17 | self._udp_port = 8895 18 | 19 | def connect(self): 20 | self.connect_tcp() 21 | self.connect_udp() 22 | 23 | def connect_tcp(self): # handshake 24 | print("Starting Handshake...") 25 | self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 26 | self.tcp_socket.connect((self._ip, self._tcp_port)) 27 | self.tcp_socket.send(HANDSHAKE_DATA) 28 | print("Handshake done!") 29 | 30 | def connect_udp(self): 31 | print("Starting drone...") 32 | self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 33 | self.udp_socket.connect((self._ip, self._udp_port)) 34 | self.droneCmd = START_DRONE_DATA[:] 35 | self.udp_socket.send(self.droneCmd) 36 | print("Drone started!") 37 | 38 | def checksum(self, data): 39 | return_data = (data[1] ^ data[2] ^ data[3] ^ data[4] ^ data[5]) & 0xFF; 40 | return return_data 41 | 42 | def disconnect(self): 43 | print("Disconnecting...") 44 | self.udp_socket.close() 45 | self.tcp_socket.close() 46 | print("Disconnected!") 47 | 48 | def cmd(self, r=127, p=127, t=15, y=127): # roll, pitch, throttle, yaw 49 | time.sleep(0.05) 50 | self.droneCmd[1] = r 51 | self.droneCmd[2] = p 52 | self.droneCmd[3] = t 53 | self.droneCmd[4] = y 54 | self.droneCmd[6] = self.checksum(self.droneCmd) 55 | self.udp_socket.send(self.droneCmd) 56 | 57 | def stop(self): 58 | time.sleep(0.05) 59 | self.udp_socket.send(START_DRONE_DATA) 60 | 61 | 62 | if __name__ == "__main__": 63 | drone = DroneControl() 64 | drone.connect() 65 | 66 | for i in range(100): 67 | drone.cmd(t=50) 68 | 69 | drone.stop() 70 | drone.disconnect() 71 | -------------------------------------------------------------------------------- /fq777/dronevideo.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import time 3 | 4 | DATA = [ 5 | bytearray([0x49, 0x54, 0x64, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 6 | 0x00, 0x0F, 0x32, 0x81, 0x95, 0x45, 0x2E, 0xF5, 0xE1, 0xA9, 7 | 0x28, 0x10, 0x86, 0x63, 0x17, 0x36, 0xC3, 0xCA, 0xE2, 0x64, 8 | 0x30, 0xA3, 0xC1, 0x5E, 0x40, 0xDE, 0x30, 0xF6, 0xD6, 0x95, 9 | 0xE0, 0x30, 0xB7, 0xC2, 0xE5, 0xB7, 0xD6, 0x5D, 0xA8, 0x65, 10 | 0x9E, 0xB2, 0xE2, 0xD5, 0xE0, 0xC2, 0xCB, 0x6C, 0x59, 0xCD, 11 | 0xCB, 0x66, 0x1E, 0x7E, 0x1E, 0xB0, 0xCE, 0x8E, 0xE8, 0xDF, 12 | 0x32, 0x45, 0x6F, 0xA8, 0x42, 0xB7, 0x33, 0x0F, 0xB7, 0xC9, 13 | 0x57, 0x82, 0xFC, 0x3D, 0x67, 0xE7, 0xC3, 0xA6, 0x67, 0x28, 14 | 0xDA, 0xD8, 0xB5, 0x98, 0x48, 0xC7, 0x67, 0x0C, 0x94, 0xB2, 15 | 0x9B, 0x54, 0xD2, 0x37, 0x9E, 0x2E, 0x7A]), 16 | 17 | bytearray([0x49, 0x54, 0x64, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 18 | 0x00, 0x54, 0xB2, 0xD1, 0xF6, 0x63, 0x48, 0xC7, 0xCD, 0xB6, 19 | 0xE0, 0x5B, 0x0D, 0x1D, 0xBC, 0xA8, 0x1B, 0xCA, 0xE2, 0x64, 20 | 0x30, 0xA3, 0xC1, 0x5E, 0x40, 0xDE, 0x30, 0xF6, 0xD6, 0x95, 21 | 0xE0, 0x30, 0xB7, 0xC2, 0xE5, 0xB7, 0xD6, 0x5D, 0xA8, 0x65, 22 | 0x9E, 0xB2, 0xE2, 0xD5, 0xE0, 0xC2, 0xCB, 0x6C, 0x59, 0xCD, 23 | 0xCB, 0x66, 0x1E, 0x7E, 0x1E, 0xB0, 0xCE, 0x8E, 0xE8, 0xDF, 24 | 0x32, 0x45, 0x6F, 0xA8, 0x42, 0xB7, 0x33, 0x0F, 0xB7, 0xC9, 25 | 0x57, 0x82, 0xFC, 0x3D, 0x67, 0xE7, 0xC3, 0xA6, 0x67, 0x28, 26 | 0xDA, 0xD8, 0xB5, 0x98, 0x48, 0xC7, 0x67, 0x0C, 0x94, 0xB2, 27 | 0x9B, 0x54, 0xD2, 0x37, 0x9E, 0x2E, 0x7A]) 28 | ] 29 | 30 | DATA1 = bytearray([0x49, 0x54, 0x64, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 31 | 0x80, 0x86, 0x38, 0xC3, 0x8D, 0x13, 0x50, 0xFD, 0x67, 0x41, 0xC2, 32 | 0xEE, 0x36, 0x89, 0xA0, 0x54, 0xCA, 0xE2, 0x64, 0x30, 0xA3, 0xC1, 33 | 0x5E, 0x40, 0xDE, 0x30, 0xF6, 0xD6, 0x95, 0xE0, 0x30, 0xB7, 0xC2, 34 | 0xE5, 0xB7, 0xD6, 0x5D, 0xA8, 0x65, 0x9E, 0xB2, 0xE2, 0xD5, 0xE0, 35 | 0xC2, 0xCB, 0x6C, 0x59, 0xCD, 0xCB, 0x66, 0x1E, 0x7E, 0x1E, 0xB0, 36 | 0xCE, 0x8E, 0xE8, 0xDF, 0x32, 0x45, 0x6F, 0xA8, 0x42, 0xEB, 0x20, 37 | 0xBE, 0x38, 0x3A, 0xAB, 0x05, 0xA8, 0xC2, 0xA7, 0x1F, 0x2C, 0x90, 38 | 0x6D, 0x93, 0xF7, 0x2A, 0x85, 0xE7, 0x35, 0x6E, 0xFF, 0xE1, 0xB8, 39 | 0xF5, 0xAF, 0x09, 0x7F, 0x91, 0x47, 0xF8, 0x7E]) 40 | 41 | class DroneVideo(object): 42 | 43 | def __init__(self): 44 | self.fh = open("fpv.mp4", 'wb') 45 | self.ip = '172.16.10.1' 46 | self.port = 8888 47 | 48 | def fetch_video(self): 49 | count = 0 50 | video = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 51 | video.connect((self.ip, self.port)) 52 | 53 | video.send(DATA[0]) 54 | print("video link", len(video.recv(8192))) 55 | video.send(DATA[1]) 56 | print("video link", len(video.recv(8192))) 57 | 58 | stream = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 59 | stream.connect((self.ip, self.port)) 60 | stream.send(DATA1) 61 | 62 | stream.settimeout(1) 63 | 64 | while True: 65 | count +=1 66 | try: 67 | data = stream.recv(8192) 68 | except socket.timeout: 69 | stream.close() 70 | video.close() 71 | return count 72 | 73 | self.fh.write(data) --------------------------------------------------------------------------------