From d7379da2e470ccb0852a928e379518a206b04e48 Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Mon, 12 Sep 2022 14:25:31 +0300 Subject: [PATCH 01/18] V2.0.1 Alpha Small fixes --- README.md | 5 +- WRITEHERE.py | 6 -- tello.py | 164 +++++++++++++++++++++++++++++++++++---------------- telloLive.py | 10 ++-- 4 files changed, 120 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index acad29e..38d607d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.0 Alpha*
+*2.0.1 Alpha*
SDK 3.0 is **here**! Documentation and testing in progress! ## Requirements: * Python installed on your system or as a VS Code extension @@ -216,6 +216,9 @@ tello.end() ``` ## Version history: +**2.0.1 Alpha** +* Small fixes + **2.0 Alpha** * All new Tello SDK 3.0 commands implemented! * Small potential bug/style fixes diff --git a/WRITEHERE.py b/WRITEHERE.py index 6c65f73..e69de29 100644 --- a/WRITEHERE.py +++ b/WRITEHERE.py @@ -1,6 +0,0 @@ -from tello import Tello - -tello = Tello() - -print(tello.throw_fly()) -tello.end() diff --git a/tello.py b/tello.py index e8f1515..97bce82 100644 --- a/tello.py +++ b/tello.py @@ -1,7 +1,7 @@ -# TODO: # !! tello.curveMpad() -- ERROR: RUN TIMEOUT ??? -from operator import contains -import string + +# Import sentry_sdk and initialize it +# More: sentry.io import sentry_sdk sentry_sdk.init( dsn="https://f2fcaa10be4f41958ab756183583ba81@o1400261.ingest.sentry.io/6728983", @@ -14,6 +14,7 @@ # Import all needed libraries +import string import socket import sys import time @@ -23,6 +24,7 @@ # Class for all functions for user class Tello: def __init__(self, prints=True): + ''' Checks network name, creates UDP socket and prints starting info to user''' # Set self variables self.sock = None @@ -36,7 +38,7 @@ def __init__(self, prints=True): # Set variables for connection to drone host = '' port = 9000 - locaddr = (host,port) + locaddr = (host, port) self.mids = 'm1 m2 m3 m4 m5 m6 m7 m8' # Print starting info for the user @@ -54,7 +56,6 @@ def __init__(self, prints=True): print(' Checking network... \r\n') time.sleep(1) - # Check what network is connected if sys.platform == 'win32': wifi = subprocess.check_output(['/windows/system32/netsh', 'WLAN', 'show', 'interfaces']) @@ -62,7 +63,7 @@ def __init__(self, prints=True): wifi_val = 'Not connected' for line in data.split('\n'): if "SSID: " in line: - key, val = line.split(': ') + _, val = line.split(': ') val = val.strip() wifi_val = val if "TELLO-" in data or "RMTT-" in data: @@ -76,8 +77,8 @@ def __init__(self, prints=True): else: sys.exit() elif sys.platform == 'darwin': - process = subprocess.Popen(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport','-I'], stdout=subprocess.PIPE) - out, err = process.communicate() + process = subprocess.Popen(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I'], stdout=subprocess.PIPE) + out, _ = process.communicate() process.wait() wifi_val = 'Not connected' for line in out.decode('utf-8').split('\n'): @@ -99,12 +100,10 @@ def __init__(self, prints=True): print('Could not determine network.') print('Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks.') - # Print info to the user print(' Making UDP socket... \r\n') time.sleep(1) - # Create UDP socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.tello_address = ('192.168.10.1', 8889) @@ -115,18 +114,20 @@ def __init__(self, prints=True): # Function to receive commands from the drone def receive(self): + '''Receives UDP messages from the drone''' while True: try: self.response, self.ip = self.sock.recvfrom(256) except Exception: break - def run(self, string: str, message: str = "No message "): + def run(self, command: str, message: str = "No message "): + '''Sends a command to the drone and waits for a response''' self.abort = False timer = threading.Timer(10, self._set_abort) # Encode the message in the utf-8 encoding - string = string.encode(encoding='utf-8') + command = string.encode(encoding='utf-8') # Send the encoded message to the Tello - self.sent = self.sock.sendto(string, self.tello_address) + self.sent = self.sock.sendto(command, self.tello_address) print(message) self.response = None timer.start() @@ -134,7 +135,7 @@ def run(self, string: str, message: str = "No message "): if self.abort is True: break timer.cancel() - if self.response == None: + if self.response is None: return 'error' if self.abort is False: response = self.response.decode(encoding='utf-8') @@ -143,34 +144,43 @@ def run(self, string: str, message: str = "No message "): return response return 'error' def _set_abort(self): + '''Sets the abort flag to True (used in run())''' self.abort = True # SDK 3.0 Commands def throw_fly(self): + '''Sends command to fly when tossed''' return self.run('throwfly', 'Gently toss the drone into the air within 5 seconds!\r\n') def motor_on(self): + '''Sends command to turn on motors''' return self.run('motoron', 'Turning on motors\r\n') def motor_off(self): + '''Sends command to turn off motors''' return self.run('motoroff', 'Turning off motors\r\n') def reboot(self): + '''Sends command to reboot the drone''' test = self.run('reboot', 'Rebooting\r\n') if test == 'error': return 'error' return 'ok' # SDK 3.0 SET Commands def rc(self, roll: int = 0, pitch: int = 0, yaw: int = 0, throttle: int = 0): + '''Sends command to adjust lever force values (acc. to official docs)''' if 100 >= roll >= -100 and 100 >= pitch >= -100 and 100 >= yaw >= -100 and 100 >= throttle >= -100: - self.run('rc %s %s %s %s' % (roll, pitch, yaw, throttle), 'Setting lever force values\r\n') + self.run(f'rc {roll} {pitch} {yaw} {throttle}', 'Setting lever force values\r\n') return 'ok' print('ERROR: Parameters must be between -100 and 100') print('ERROR LOCATION: tello.rc()') return 'error' def ap(self, ssid: str, password: str): - return self.run('ap %s %s' % (ssid, password), 'Connecting to access point, then rebooting\r\n') + '''Sends command to set Tello to station mode, connect to access point and reboot''' + return self.run(f'ap {ssid} {password}', 'Connecting to access point, then rebooting\r\n') def set_wifi_channel(self, channel: int): - return self.run('wifi %s' % channel, 'Setting Wi-Fi channel to ' + channel + '\r\n') + '''Sends command to set the WiFi channel''' + return self.run(f'wifi {channel}', f'Setting Wi-Fi channel to {channel} channel\r\n') def set_port(self, info_port: int, video_port: int): + '''Sends command to set the port for the info and video streams''' if 1025 <= info_port <= 65535 and 1025 <= video_port <= 65535: - ports = self.run('port %s %s' % (info_port, video_port), 'Setting new ports for status and video\r\n') + ports = self.run(f'port {info_port} {video_port}', 'Setting new ports for status and video\r\n') if ports == 'ok': self.tello_address = ('192.168.10.1', info_port) # @@ -180,40 +190,52 @@ def set_port(self, info_port: int, video_port: int): return 'error' return 'error' def set_fps(self, fps: str): + '''Sends command to set the video stream frame rate''' if fps in ('h', 'm', 'l', 'high', 'medium', 'low'): - return self.run('setfps %s' % fps, 'Setting FPS to ' + fps + '\r\n') + return self.run(f'setfps {fps}', f'Setting FPS to {fps} fps \r\n') return 'error' def set_bitrate(self, bitrate: int): + '''Sends command to set the video stream bitrate''' if 1 <= bitrate <= 5: - return self.run('setbitrate %s' % bitrate, 'Setting bitrate to ' + bitrate + ' Mbps\r\n') + return self.run(f'setbitrate {bitrate}', f'Setting bitrate to {bitrate} Mbps\r\n') elif bitrate == 0: - return self.run('setbitrate %s' % bitrate, 'Setting bitrate to auto\r\n') + return self.run(f'setbitrate {bitrate}', 'Setting bitrate to auto\r\n') return 'error' def set_resolution(self, resolution: str): + '''Sends command to set the video stream resolution''' if resolution in ('h', 'l', 'high', 'low'): - return self.run('setresolution %s' % resolution, 'Setting resolution to ' + resolution + '\r\n') + return self.run(f'setresolution {resolution}', f'Setting resolution to {resolution} \r\n') return 'error' def set_rmtt_wifi(self, ssid: str, password: str): - return self.run('multwifi %s %s' % (ssid, password), 'Setting RMTT SSID and password to %s %s\r\n' % (ssid, password)) + '''Sends command to Tello to set the RMTT WiFi network ssid and password (RMTT only)''' + return self.run(f'multwifi {ssid} {password}', f'Setting RMTT SSID and password to {ssid} {password} \r\n') # SDK 2.0 Commands def connect(self): + '''Sends command to initalize SDK mode''' return self.run('command', '\r\nEnabling SDK mode\r\n') def takeoff(self): + '''Sends command to takeoff''' return self.run('takeoff', 'Taking off, keep clear of drone!\r\n') def land(self): + '''Sends command to land''' return self.run('land', 'Landing, keep space clear!\r\n') def video_stream_on(self): + '''Sends command to start video stream''' return self.run('streamon', 'Enabling video stream\r\n') def video_stream_off(self): + '''Sends command to stop video stream''' return self.run('streamoff', 'Disabling video stream\r\n') def emergency(self, reason='No reason provided'): + '''Sends command to stop all motors''' print('EMERGENCY: Reason:', reason, '\r\n') print('EMERGENCY: Exiting script') self.run('emergency', 'EMERGENCY: Disabling motors\r\n') sys.exit() - def stop(self): + def stop_movement(self): + '''Sends command to stop movement and hover''' return self.run('stop', 'Stopping all movement, hovering.\r\n') def up(self, x: int): + '''Sends command to move up x cm''' if x >= 20 and x <= 500: a = ' '.join(['up', str(x)]) message = ' '.join(['Ascending to', str(x), 'cm from the ground \r\n']) @@ -221,100 +243,122 @@ def up(self, x: int): print('\r\nERROR: Parameter must be between 20 and 500') print('ERROR LOCATION: tello.down()\r\n') def down(self, x: int): + '''Sends command to move down x cm''' if x >= 20 and x <= 500: a = ' '.join(['down', str(x)]) return self.run(a, ' '.join(['Descending to', str(x), 'cm from the ground \r\n'])) print('\r\nERROR: Parameter must be between 20 and 500\r\n') print('ERROR LOCATION: tello.down()\r\n') def left(self, x: int): + '''Sends command to move left x cm''' if x >= 20 and x <= 500: a = ' '.join(['left', str(x)]) return self.run(a, ' '.join(['Moving left', str(x), 'cm, keep clear of drone\'s path \r\n'])) print('\r\nERROR: Parameter must be between 20 and 500') print('ERROR LOCATION: tello.left()\r\n') def right(self, x: int): + '''Sends command to move right x cm''' if x >= 20 and x <= 500: a = ' '.join(['right', str(x)]) return self.run(a, ' '.join(['Moving right', str(x), 'cm, keep clear of drone\'s path \r\n'])) print('\r\nERROR: Parameter must be between 20 and 500') print('ERROR LOCATION: tello.right()\r\n') def forward(self, x: int): + '''Sends command to move forward x cm''' if x >= 20 and x <= 500: a = ' '.join(['forward', str(x)]) return self.run(a, ' '.join(['Moving forward', str(x), 'cm, keep clear of drone\'s path \r\n'])) print('\r\nERROR: Parameter must be between 20 and 500') print('ERROR LOCATION: tello.forward()\r\n') def back(self, x: int ): + '''Sends command to move back x cm''' if x >= 20 and x <= 500: a = ' '.join(['back', str(x)]) return self.run(a, ' '.join(['Moving forward', str(x), 'cm, keep clear of drone\'s path \r\n'])) print('\r\nERROR: Parameter must be between 20 and 500') print('ERROR LOCATION: tello.back()\r\n') def cw(self, x: int): + '''Sends command to rotate clockwise x degrees''' if x >= 1 and x <= 360: a = ' '.join(['cw', str(x)]) return self.run(a, ' '.join(['Rotating clockwise for', str(x), 'degrees \r\n'])) print('\r\nERROR: Parameter must be between 1 and 360') print('ERROR LOCATION: tello.cw()\r\n') def ccw(self, x: int): + '''Sends command to rotate counter-clockwise x degrees''' if x >= 1 and x <= 360: a = ' '.join(['ccw', str(x)]) return self.run(a, ' '.join(['Rotating counter-clockwise for', str(x), 'degrees \r\n'])) print('\r\nERROR: Parameter must be between 1 and 360') print('ERROR LOCATION: tello.ccw()\r\n') def flip(self, x: int): + '''Sends command to flip in direction x''' if x in ('l', 'r', 'f', 'b'): a = ' '.join(['flip', x]) return self.run(a, ' '.join(['Flipping', str(x), ', be careful \r\n'])) print('\r\nERROR: Parameter must be either f, b, r, or l!') print('ERROR LOCATION: tello.flip()\r\n') def set_speed(self, x: int): + '''Sends command to set speed to x cm/s''' if x >= 1 and x <= 100: a = ' '.join(['speed', str(x)]) return self.run(a, ' '.join(['Setting speed to', str(x), 'cm/s \r\n'])) print('\r\nERROR: Parameter must be between 10 and 100') print('ERROR LOCATION: tello.setSpeed()\r\n') def set_wifi(self, ssid: str, passw: str): + '''Sends command to set wifi to ssid and passw''' return self.run(' '.join(['wifi', ssid, passw]), ' '.join(['Setting wifi to', ssid, 'with password', passw, 'then rebooting\r\n'])) def set_mission_on(self): + '''Sends command to set mission pad detection on''' return self.run('mon', 'Enabling Mission Pad detection\r\n') def set_mission_off(self): + '''Sends command to set mission pad detection off''' return self.run('moff', 'Disabling Mission Pad detection\r\n') def set_mission_direction(self, x: int): + '''Sends command to set mission pad detection direction to x''' if x >= 0 and x <= 3: a = ' '.join(['mdirection', str(x)]) return self.run(a, ' '.join(['Setting Mission Pad Detection to setting', str(x), '\r\n'])) - else: - print('\r\nERROR: Parameter must be between 0 and 3') - print('ERROR LOCATION: tello.setMdircetion()\r\n') + print('\r\nERROR: Parameter must be between 0 and 3') + print('ERROR LOCATION: tello.setMdircetion()\r\n') # GET Commands def get_speed(self): + '''Sends command to get speed''' return self.run('speed?', 'Obtaining current speed \r\n') def get_battery(self): + '''Sends command to get battery''' return self.run('battery?', 'Obtaining battery level \r\n') def get_time(self): + '''Sends command to get flight time''' return self.run('time?', 'Obtaining current flight time \r\n') def get_wifi(self): + '''Sends command to get wifi info''' return self.run('wifi?', 'Obtaining WiFi SNR \r\n') def get_sdk(self): + '''Sends command to get SDK version''' return self.run('sdk?', 'Obtaining Tello SDK Version \r\n') def get_sn(self): + '''Sends command to get serial number''' return self.run('sn?', 'Obtaining Tello serial number \r\n') - #SDK 3.0 GET Commands + # SDK 3.0 GET Commands def get_hardware(self): + '''Sends command to get hardware (RMTT or Tello)''' return self.run('hardware?', 'Obtaining hardware status \r\n') - def get_wifi_version(self): + def get_rmtt_wifi_version(self): + '''Sends command to get rmtt wifi version''' return self.run('wifi?', 'Obtaining RMTT WiFi version \r\n') def get_ap(self): + '''Sends command to get rmtt ap info''' return self.run('ap?', 'Obtaining RMTT Access Point SSID and password \r\n') def get_ssid(self): + '''Sends command to get rmtt ssid info''' return self.run('ssid?', 'Obtaining RMTT WiFi SSID and password (if any) \r\n') - # COMPLEX Commands def go(self, x: int, y: int, z: int, s: int): + '''Sends command to move to x y z at speed s''' if 500 >= x >= -500 and 500 >= y >= -500 and 500 >= z >= -500: if 100 >= s >= 10: a = ' '.join(['go', str(x), str(y), str(z), str(s)]) @@ -325,6 +369,7 @@ def go(self, x: int, y: int, z: int, s: int): print('\r\nERROR: Parameters x, y, z need to be between 500 and -500!') print('ERROR LOCATION: tello.go()\r\n') def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): + '''Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2''' if 500 >= x1 >= -500 and 500 >= x2 >= -500 and 500 >= y1 >= -500 and 500 >= y2 >= -500 and 500 >= z1 >= -500 and 500 >= z2 >= -500: if 60 >= s >= 10: a = ' '.join(['curve', str(x1), str(x2), str(y1), str(y2), str(z1), str(z2), str(s)]) @@ -335,6 +380,7 @@ def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): print('\r\nERROR: Parameters x1, x2, y1, y2, z1, z2 need to be between 500 and -500!') print('ERROR LOCATION: tello.curve()\r\n') def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): + '''Sends command to move to x y z at speed s to mission pad mid''' mid_ok = False for id in self.mids.split(' '): if id == mid: @@ -354,6 +400,7 @@ def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): print('\r\nERROR: Parameters x, y, z need to be between 500 and -500!') print('ERROR LOCATION: tello.goMpad()\r\n') def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int, mid: str): + '''Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2 to mission pad mid''' mid_ok = False for id in self.split(' '): if id == mid: @@ -376,30 +423,34 @@ def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int # SDK 3.0 DISPLAY Commands # def set_light_color(self, r: int, g: int, b: int): + '''Sends command to set the color of the LED''' if 255 >= r >= 0 and 255 >= g >= 0 and 255 >= b >= 0: - a = ' '.join(['EXT led', str(r), str(g), str(b)]) - return self.run(a, ' '.join(['Setting RMTT light color to (r, g, b):', str(r), str(g), str(b), '\r\n'])) + a = f'EXT led {str(r)} {str(g)} {str(b)}' + return self.run(a, f'Setting RMTT light color to (r, g, b): {str(r)}, {str(g)}, {str(b)}\r\n') print('\r\nERROR: Parameters r, g, b need to be between 255 and 0!') print('ERROR LOCATION: tello.set_light_color()\r\n') return 'led error' def set_light_pulse(self, r: int, g: int, b: int, p: float or int): + '''Sends command to set the color and pulse of the LED''' if 255 >= r >= 0 and 255 >= g >= 0 and 255 >= b >= 0 and 2.5 >= p >= 0.1: - a = ' '.join(['EXT led', str(p), str(r), str(g), str(b)]) - return self.run(a, ' '.join(['Setting RMTT light color to (r, g, b):', str(r), str(g), str(b), 'with pulse of', str(p), 'Hz\r\n'])) + a = f'EXT led {str(p)} {str(r)} {str(g)} {str(b)}' + return self.run(a, f'Setting RMTT light color to (r, g, b):, {str(r)}, {str(g)}, {str(b)}, with pulse of, {str(p)}, Hz\r\n') print('\r\nERROR: Parameters r, g, b need to be between 255 and 0!') print('ERROR LOCATION: tello.set_light_pulse()\r\n') return 'led error' def set_light_flash(self, r1: int, g1: int, b1: int, r2: int, g2: int, b2: int, f: float or int): + '''Sends command to set the 2 colors to flash of the LED''' if 255 >= r1 >= 0 and 255 >= g1 >= 0 and 255 >= b1 >= 0 and 255 >= r2 >= 0 and 255 >= g2 >= 0 and 255 >= b2 >= 0 and 2.5 >= f >= 0.1: - a = ' '.join(['EXT led', str(f), str(r1), str(g1), str(b1), str(r2), str(g2), str(b2)]) - return self.run(a, ' '.join(['Setting RMTT light color to (r1, g1, b1):', str(r1), str(g1), str(b1), 'and (r2, g2, b2):', str(r2), str(g2), str(b2), 'with flash of', str(f), 'Hz\r\n'])) + a = f'EXT led {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}' + return self.run(a, f'Setting RMTT light color to (r1, g1, b1): {str(r1)}, {str(g1)}, {str(b1)} and (r2, g2, b2): {str(r2)}, {str(g2)}, {str(b2)} with flash of {str(f)} Hz\r\n') print('\r\nERROR: Parameters r1, g1, b1, r2, g2, b2 need to be between 255 and 0, f between 0.1 and 10!') print('ERROR LOCATION: tello.set_light_flash()\r\n') return 'led error' def set_display_pattern(self, pattern: str): + '''Sends command to set the display pattern''' if pattern.split('') in ('r', 'b', 'p', '0') and 64 > pattern.length > 1: - a = ' '.join(['EXT mled g', str(pattern)]) - return self.run(a, ' '.join(['Setting RMTT display pattern to:', str(pattern), '\r\n'])) + a = f'EXT mled g {str(pattern)}' + return self.run(a, f'Setting RMTT display pattern to: {str(pattern)} \r\n') print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 64 characters!') print('ERROR LOCATION: tello.set_display_pattern()\r\n') return 'mled error' @@ -407,9 +458,10 @@ def set_display_pattern(self, pattern: str): # AWAITING TESTING # def set_display_string_direction(self, direction: str, color: str, frame_rate: float or int, pattern: str): + '''Sends command to set the display string direction''' # TO BE CHANGED if direction.split('') in ('l', 'r', 'u', 'd') and color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1 and 70 > pattern.length > 1 and pattern.split('') in ('r', 'b', 'p', '0'): - a = ' '.join(['EXT mled', str(direction), str(color), str(frame_rate), str(pattern)]) - return self.run(a, ' '.join(['Setting RMTT string display direction to:', str(direction), 'with color:', str(color), 'and frame rate:', str(frame_rate), 'and pattern:', str(pattern), '\r\n'])) + a = f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}' + return self.run(a, f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)} and frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n') print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 70 characters, color must contain r, b, or p, direction can contain only u, d, l, r, and frame rate can be a int or float between 0.1 and 10!') print('ERROR LOCATION: tello.set_display_string_direction()\r\n') return 'mled error' @@ -417,45 +469,53 @@ def set_display_string_direction(self, direction: str, color: str, frame_rate: f # AWAITING TESTING # def set_display_image_direction(self, direction: str, color: str, frame_rate: float or int, pattern: str): + '''Sends command to set the display image direction''' # TO BE CHANGED if direction.split('') in ('l', 'r', 'u', 'd') and color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1 and 70 > pattern.length > 1 and pattern.split('') in ('r', 'b', 'p', '0'): - a = ' '.join(['EXT mled', str(direction), str(color), str(frame_rate), str(pattern)]) - return self.run(a, ' '.join(['Setting RMTT string display direction to:', str(direction), 'with color:', str(color), 'and frame rate:', str(frame_rate), 'and pattern:', str(pattern), '\r\n'])) + a = f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}' + return self.run(a, f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)} and frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n') print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 70 characters, color must contain r, b, or p, direction can contain only u, d, l, r, and frame rate can be a int or float between 0.1 and 10!') print('ERROR LOCATION: tello.set_display_image_direction()\r\n') return 'mled error' def set_display_ascii_character(self, character: str, color: str): + '''Sends command to display an ascii charachter on the display''' if character == 'heart' or character == string.printable and color in ('r', 'b', 'p'): - a = ' '.join(['EXT mled s', str(character), str(color)]) - return self.run(a, ' '.join(['Displaying ASCII character:', str(character), 'with color:', str(color), '\r\n'])) + a = f'EXT mled s {str(character)}, {str(color)}' + return self.run(a, f'Displaying ASCII character: {str(character)} with color: {str(color)} \r\n') print('\r\nERROR: Parameter character needs to be a printable character or "heart", and color must contain r, b, or p!') print('ERROR LOCATION: tello.set_display_ascii_character()\r\n') return 'mled error' def set_display_boot(self, pattern: str): + '''Sends command to set the boot animation for the display ''' if pattern.split('') in ('r', 'b', 'p', '0') and 64 > pattern.length > 1: - a = ' '.join(['EXT mled sg', str(pattern)]) - return self.run(a, ' '.join(['Setting RMTT boot display pattern to:', str(pattern), '\r\n'])) + a = f'EXT mled sg {str(pattern)}' + return self.run(a, f'Setting RMTT boot display pattern to: {str(pattern)} \r\n') print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 64 characters!') print('ERROR LOCATION: tello.set_display_boot()\r\n') return 'mled error' def clear_display_boot(self): + '''Sends command to clear boot animation for the display ''' a = 'EXT mled sc' - return self.run(a, ' '.join(['Clearing RMTT boot display pattern\r\n'])) + return self.run(a, 'Clearing RMTT boot display pattern\r\n') def set_display_brightness(self, brightness: int): + '''Sends command to set the display brightness''' if 255 >= brightness >= 0: - a = ' '.join(['EXT mled sl', str(brightness)]) - return self.run(a, ' '.join(['Setting RMTT display brightness to:', str(brightness), '\r\n'])) + a = f'EXT mled sl {str(brightness)}' + return self.run(a, f'Setting RMTT display brightness to: {str(brightness)} \r\n') print('\r\nERROR: Parameter brightness needs to be between 0 and 255!') print('ERROR LOCATION: tello.set_display_brightness()\r\n') return 'mled error' def get_height(self): + '''Sends command to get the height of the drone from ground''' a = 'EXT tof?' - return self.run(a, ' '.join(['Getting height...\r\n'])) + return self.run(a, 'Getting height...\r\n') def get_rmtt_version(self): + '''Sends command to get the open-source controller (RMTT) version''' a = 'EXT version?' - return self.run(a, ' '.join(['Getting RMTT version...\r\n'])) - + return self.run(a, 'Getting RMTT version...\r\n') + # End command def end(self): + '''Sends end command to Tello''' self.sock.close() print('Exiting...') return 'ok' diff --git a/telloLive.py b/telloLive.py index 709d3a6..a99e0ef 100644 --- a/telloLive.py +++ b/telloLive.py @@ -12,7 +12,7 @@ host = '' port = 9000 -locaddr = (host,port) +locaddr = (host, port) # Print general info for the user @@ -32,7 +32,7 @@ try: - process = subprocess.Popen(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport','-I'], stdout=subprocess.PIPE) + process = subprocess.Popen(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I'], stdout=subprocess.PIPE) out, err = process.communicate() process.wait() wifi_val = {} @@ -52,7 +52,7 @@ else: print('Network detected:', wifi_val) print('No errors. \r\n') -except: +except subprocess.SubprocessError: print('\r\nSeems like there was an error checking the network.') print('Aborting script.\r\n') sys.exit() @@ -74,7 +74,7 @@ def recv(): while True: try: - data, server = sock.recvfrom(1518) + data, _ = sock.recvfrom(1518) data = data.decode(encoding='utf-8') if data == 'ok': print('Operation successful\r\n') @@ -88,7 +88,6 @@ def recv(): break - print("\r\nTo view all available functions, type", '\033[1m' + 'help' + '\033[0m') print("\r\nTo quit the script, type", '\033[1m' + 'end' + '\033[0m') print("\r\n(For emergencies) To immediately quit the script, press", '\033[1m' + 'Ctrl + C' + '\033[0m') @@ -96,7 +95,6 @@ def recv(): print("\r\nTo begin, type", '\033[1m' + 'command' + '\033[0m: \r\n') - #recvThread create recvThread = threading.Thread(target=recv) recvThread.start() From c0a89824e9b13b682fb20229c3e222c8489adadc Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Mon, 12 Sep 2022 18:32:10 +0300 Subject: [PATCH 02/18] V2.0.2 Alpha Style fixes (code cleanup), new Tello class parameters, all-new logging and started on going pip-ready! --- README.md | 8 +- tello.py | 845 ++++++++++++++++++++++++++++++++++----------------- telloLive.py | 36 +-- 3 files changed, 593 insertions(+), 296 deletions(-) diff --git a/README.md b/README.md index 38d607d..e02e87e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.0.1 Alpha*
+*2.0.2 Alpha*
SDK 3.0 is **here**! Documentation and testing in progress! ## Requirements: * Python installed on your system or as a VS Code extension @@ -216,6 +216,12 @@ tello.end() ``` ## Version history: +**2.0.2 Alpha** +* Style fixes +* Started work on going pip-ready :) +* Changed all print to logging (for easier debugging) +* Added debugging and tips options to Tello class + **2.0.1 Alpha** * Small fixes diff --git a/tello.py b/tello.py index 97bce82..94a3b9e 100644 --- a/tello.py +++ b/tello.py @@ -1,18 +1,5 @@ # !! tello.curveMpad() -- ERROR: RUN TIMEOUT ??? -# Import sentry_sdk and initialize it -# More: sentry.io -import sentry_sdk -sentry_sdk.init( - dsn="https://f2fcaa10be4f41958ab756183583ba81@o1400261.ingest.sentry.io/6728983", - - # Set traces_sample_rate to 1.0 to capture 100% - # of transactions for performance monitoring. - # We recommend adjusting this value in production. - traces_sample_rate=1.0 -) - - # Import all needed libraries import string import socket @@ -20,13 +7,51 @@ import time import threading import subprocess +import sentry_sdk +import logging + +# Initialize Sentry (error catching) +# We will be able to see the name of your computer, the error, and the line of code that caused it. +# Delete the following 4 lines to opt out +# More: sentry.io + +# ------------------ # +sentry_sdk.init( + dsn="https://f2fcaa10be4f41958ab756183583ba81@o1400261.ingest.sentry.io/6728983", + traces_sample_rate=1.0 +) +# ------------------ # + # Class for all functions for user -class Tello: - def __init__(self, prints=True): - ''' Checks network name, creates UDP socket and prints starting info to user''' +class Tello(): + """Class for info commands to the Tello or RMTT drones""" + + + def __init__(self, log_in_console: bool = True, tips: bool = True): + """Checks network name, creates UDP socket and prints starting info to user""" + # Configure logging + if log_in_console: + logging.basicConfig( + format='%(asctime)s [%(levelname)s] %(message)s ', + datefmt='%H:%M:%S', + level=logging.INFO, + handlers=[ + logging.StreamHandler(sys.stdout), + logging.FileHandler('debug.log', mode='w') + ] + ) + else: + logging.basicConfig( + format='%(asctime)s [%(levelname)s] %(message)s ', + datefmt='%H:%M:%S', + level=logging.DEBUG, + filename='debug.log', + filemode='w' + ) # Set self variables + self.tips = tips self.sock = None self.response = None self.tello_address = None @@ -42,19 +67,19 @@ def __init__(self, prints=True): self.mids = 'm1 m2 m3 m4 m5 m6 m7 m8' # Print starting info for the user - print('_________ ____ ____ ') - print(' | | | | | |') - print(' | |___ | | | |') - print(' | | | | | |') - print(' | |____ |____ |____ |____|\r\n') - print(' Drone Script ') - print(' File edition! \r\n') - time.sleep(0.5) - print(' Initializing... \r\n') - time.sleep(1) + logging.info('--------------------------------------') + logging.info('_________ ____ ____ ') + logging.info(' | | | | | |') + logging.info(' | |___ | | | |') + logging.info(' | | | | | |') + logging.info(' | |____ |____ |____ |____|\r\n') + logging.info(' Drone Script ') + logging.info('--------------------------------------') - print(' Checking network... \r\n') - time.sleep(1) + logging.debug(f'Current port for UDP connection: {str(port)}') + + logging.info(' Checking network... \r\n') + time.sleep(0.5) # Check what network is connected if sys.platform == 'win32': @@ -67,17 +92,15 @@ def __init__(self, prints=True): val = val.strip() wifi_val = val if "TELLO-" in data or "RMTT-" in data: - print('Required network detected.') + logging.debug('Required network detected.') else: - print('Network detected') - print('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') - approval = input("Are you sure you want to continue with the script? (y/n)") - if approval == 'y': - print('\r\n') - else: - sys.exit() + logging.debug('Network detected') + logging.warning('It seems like you have not joined the TELLO- or RMTT-network. Please make sure that you have joined the TELLO- or RMTT- Wi-Fi.') elif sys.platform == 'darwin': - process = subprocess.Popen(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I'], stdout=subprocess.PIPE) + process = subprocess.Popen([ + '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', + '-I' + ], stdout=subprocess.PIPE) out, _ = process.communicate() process.wait() wifi_val = 'Not connected' @@ -87,48 +110,49 @@ def __init__(self, prints=True): val = val.strip() wifi_val = val if 'TELLO-' not in wifi_val or 'RMTT-' not in wifi_val: - print('Network detected:', wifi_val) - print('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') - approval = input("Are you sure you want to continue with the script? (y/n)") - if approval == 'y': - print('\r\n') - else: - sys.exit() + logging.debug(f'Network detected: {wifi_val}') + logging.warning('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') else: - print('Required network detected:', wifi_val) + logging.debug('Required network detected:', wifi_val) else: - print('Could not determine network.') - print('Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks.') + logging.warning('Could not determine network.') + logging.warning('Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks.') # Print info to the user - print(' Making UDP socket... \r\n') + logging.info(' Making UDP socket... \r\n') time.sleep(1) # Create UDP socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.tello_address = ('192.168.10.1', 8889) self.sock.bind(locaddr) + logging.debug('Socket created.') + logging.debug(f'Socket bound to: {str(locaddr)}') self.recvThread = threading.Thread(target=self.receive) self.recvThread.start() + logging.debug('Receive thread started.') + logging.debug('--------------------------------------\r\n') # Function to receive commands from the drone def receive(self): - '''Receives UDP messages from the drone''' + """Receives UDP messages from the drone""" while True: try: self.response, self.ip = self.sock.recvfrom(256) except Exception: break - def run(self, command: str, message: str = "No message "): - '''Sends a command to the drone and waits for a response''' + + def run(self, command: str, message: str = "No tips available for this command "): + """Sends command to the drone and prints message to the user""" self.abort = False timer = threading.Timer(10, self._set_abort) # Encode the message in the utf-8 encoding - command = string.encode(encoding='utf-8') + command = command.encode(encoding='utf-8') # Send the encoded message to the Tello self.sent = self.sock.sendto(command, self.tello_address) - print(message) + if self.tips: + logging.info(message) self.response = None timer.start() while self.response is None: @@ -136,251 +160,475 @@ def run(self, command: str, message: str = "No message "): break timer.cancel() if self.response is None: + logging.warning('Command timed out.') return 'error' if self.abort is False: response = self.response.decode(encoding='utf-8') - print(response) self.response = None + logging.debug(f'Response to previous command: {response}') return response return 'error' + def _set_abort(self): - '''Sets the abort flag to True (used in run())''' + """Sets the abort variable to True""" self.abort = True + return None + # SDK 3.0 Commands def throw_fly(self): - '''Sends command to fly when tossed''' - return self.run('throwfly', 'Gently toss the drone into the air within 5 seconds!\r\n') + """Sends command to the drone to fly when tossed""" + logging.debug('Sending command: throw_fly()') + return self.run( + 'throwfly', + 'Gently toss the drone into the air within 5 seconds!\r\n' + ) + def motor_on(self): - '''Sends command to turn on motors''' - return self.run('motoron', 'Turning on motors\r\n') + """Sends command to turn on motors""" + logging.debug('Sending command: motor_on()') + return self.run( + 'motoron', + 'Turning on motors\r\n' + ) + def motor_off(self): - '''Sends command to turn off motors''' - return self.run('motoroff', 'Turning off motors\r\n') + """Sends command to turn off motors""" + logging.debug('Sending command: motor_off()') + return self.run( + 'motoroff', + 'Turning off motors\r\n' + ) + def reboot(self): - '''Sends command to reboot the drone''' - test = self.run('reboot', 'Rebooting\r\n') + """Sends command to reboot the drone""" + logging.debug('Sending command: reboot()') + test = self.run( + 'reboot', + 'Rebooting\r\n' + ) if test == 'error': + logging.warning('Reboot failed.') return 'error' + logging.info('Rebooting. Please wait 30 seconds.') return 'ok' + # SDK 3.0 SET Commands def rc(self, roll: int = 0, pitch: int = 0, yaw: int = 0, throttle: int = 0): - '''Sends command to adjust lever force values (acc. to official docs)''' + """Sends command to adjust lever force values (acc. to official docs)""" + logging.debug('Sending command: rc()') if 100 >= roll >= -100 and 100 >= pitch >= -100 and 100 >= yaw >= -100 and 100 >= throttle >= -100: - self.run(f'rc {roll} {pitch} {yaw} {throttle}', 'Setting lever force values\r\n') + self.run( + f'rc {roll} {pitch} {yaw} {throttle}', + 'Setting lever force values\r\n' + ) return 'ok' - print('ERROR: Parameters must be between -100 and 100') - print('ERROR LOCATION: tello.rc()') + logging.warning('tello.rc(): Invalid value.') return 'error' + def ap(self, ssid: str, password: str): - '''Sends command to set Tello to station mode, connect to access point and reboot''' - return self.run(f'ap {ssid} {password}', 'Connecting to access point, then rebooting\r\n') + """Sends command to join access point, then reboot""" + logging.debug('Sending command: ap()') + return self.run( + f'ap {ssid} {password}', + 'Connecting to access point, then rebooting\r\n' + ) + def set_wifi_channel(self, channel: int): '''Sends command to set the WiFi channel''' - return self.run(f'wifi {channel}', f'Setting Wi-Fi channel to {channel} channel\r\n') + logging.debug('Sending command: set_wifi_channel()') + return self.run( + f'wifi {channel}', + f'Setting Wi-Fi channel to {channel} channel\r\n' + ) + def set_port(self, info_port: int, video_port: int): - '''Sends command to set the port for the info and video streams''' + """Sends command to set the ports for status and video""" + logging.debug('Sending command: set_port()') if 1025 <= info_port <= 65535 and 1025 <= video_port <= 65535: - ports = self.run(f'port {info_port} {video_port}', 'Setting new ports for status and video\r\n') + ports = self.run( + f'port {info_port} {video_port}', + 'Setting new ports for status and video\r\n' + ) if ports == 'ok': + logging.info(f'New ports set by client: {info_port} and {video_port}') + self.info_port = info_port self.tello_address = ('192.168.10.1', info_port) # # SET VIDEO PORT # return 'ok' + logging.warning('tello.set_port(): Failed to set ports.') + logging.debug('Failed to set ports due to an error response from the drone.') return 'error' + logging.warning('tello.set_port(): Invalid value.') return 'error' + def set_fps(self, fps: str): - '''Sends command to set the video stream frame rate''' + """Sends command to set the video stream frame rate""" + logging.debug('Sending command: set_fps()') if fps in ('h', 'm', 'l', 'high', 'medium', 'low'): - return self.run(f'setfps {fps}', f'Setting FPS to {fps} fps \r\n') + return self.run( + f'setfps {fps}', + f'Setting FPS to {fps} fps \r\n' + ) + logging.warning('tello.set_fps(): Invalid value.') return 'error' + def set_bitrate(self, bitrate: int): - '''Sends command to set the video stream bitrate''' + """Sends command to set the video stream bitrate""" + logging.debug('Sending command: set_bitrate()') if 1 <= bitrate <= 5: - return self.run(f'setbitrate {bitrate}', f'Setting bitrate to {bitrate} Mbps\r\n') - elif bitrate == 0: - return self.run(f'setbitrate {bitrate}', 'Setting bitrate to auto\r\n') + return self.run( + f'setbitrate {bitrate}', + f'Setting bitrate to {bitrate} Mbps\r\n' + ) + if bitrate == 0: + return self.run( + f'setbitrate {bitrate}', + 'Setting bitrate to auto\r\n' + ) + logging.warning('tello.set_bitrate(): Invalid value.') return 'error' + def set_resolution(self, resolution: str): - '''Sends command to set the video stream resolution''' + """Sends command to set the video stream resolution""" + logging.debug('Sending command: set_resolution()') if resolution in ('h', 'l', 'high', 'low'): - return self.run(f'setresolution {resolution}', f'Setting resolution to {resolution} \r\n') + return self.run( + f'setresolution {resolution}', + f'Setting resolution to {resolution} \r\n' + ) + logging.warning('tello.set_resolution(): Invalid value.') return 'error' + def set_rmtt_wifi(self, ssid: str, password: str): - '''Sends command to Tello to set the RMTT WiFi network ssid and password (RMTT only)''' - return self.run(f'multwifi {ssid} {password}', f'Setting RMTT SSID and password to {ssid} {password} \r\n') + """Sends command to set the RMTT WiFi SSID and password""" + logging.debug('Sending command: set_rmtt_wifi()') + return self.run( + f'multwifi {ssid} {password}', + f'Setting RMTT SSID and password to {ssid} {password} \r\n' + ) + # SDK 2.0 Commands def connect(self): - '''Sends command to initalize SDK mode''' - return self.run('command', '\r\nEnabling SDK mode\r\n') + """Sends command to initialize SDK mode""" + logging.debug('Sending command: connect()') + return self.run( + 'command', + 'Enabling SDK mode\r\n' + ) + def takeoff(self): - '''Sends command to takeoff''' - return self.run('takeoff', 'Taking off, keep clear of drone!\r\n') + """Sends command to take off""" + logging.debug('Sending command: takeoff()') + return self.run( + 'takeoff', + 'Taking off, keep clear of drone!\r\n' + ) + def land(self): - '''Sends command to land''' - return self.run('land', 'Landing, keep space clear!\r\n') + """Sends command to land""" + logging.debug('Sending command: land()') + return self.run( + 'land', + 'Landing, keep space clear!\r\n' + ) + def video_stream_on(self): - '''Sends command to start video stream''' - return self.run('streamon', 'Enabling video stream\r\n') + """Sends command to turn on video stream""" + logging.debug('Sending command: video_stream_on()') + return self.run( + 'streamon', + 'Enabling video stream\r\n' + ) + def video_stream_off(self): - '''Sends command to stop video stream''' - return self.run('streamoff', 'Disabling video stream\r\n') + """Sends command to turn off video stream""" + logging.debug('Sending command: video_stream_off()') + return self.run( + 'streamoff', + 'Disabling video stream\r\n' + ) + def emergency(self, reason='No reason provided'): - '''Sends command to stop all motors''' - print('EMERGENCY: Reason:', reason, '\r\n') - print('EMERGENCY: Exiting script') - self.run('emergency', 'EMERGENCY: Disabling motors\r\n') + """Sends command to stop all motors""" + logging.debug('Sending command: emergency()') + self.run( + 'emergency', + 'Emergency stop. Attempting to stop motors.\r\n' + ) + logging.critical('Emergency stop. Exiting script.') + logging.debug(f'Emergency stop due to: {reason}. Unable to continue due to motor stop. Exiting.') sys.exit() + def stop_movement(self): - '''Sends command to stop movement and hover''' - return self.run('stop', 'Stopping all movement, hovering.\r\n') + """Sends command to stop all movement""" + logging.debug('Sending command: stop_movement()') + return self.run( + 'stop', + 'Stopping all movement, hovering.\r\n' + ) + def up(self, x: int): - '''Sends command to move up x cm''' + """Sends command to move up x cm""" + logging.debug('Sending command: up()') if x >= 20 and x <= 500: - a = ' '.join(['up', str(x)]) - message = ' '.join(['Ascending to', str(x), 'cm from the ground \r\n']) - return self.run(a, message) - print('\r\nERROR: Parameter must be between 20 and 500') - print('ERROR LOCATION: tello.down()\r\n') + return self.run( + f'up {str(x)}', + f'Ascending to {str(x)} cm from the ground \r\n' + ) + logging.warning('tello.up(): Invalid value.') + return 'error' + def down(self, x: int): - '''Sends command to move down x cm''' + """Sends command to move down x cm""" + logging.debug('Sending command: down()') if x >= 20 and x <= 500: - a = ' '.join(['down', str(x)]) - return self.run(a, ' '.join(['Descending to', str(x), 'cm from the ground \r\n'])) - print('\r\nERROR: Parameter must be between 20 and 500\r\n') - print('ERROR LOCATION: tello.down()\r\n') - def left(self, x: int): - '''Sends command to move left x cm''' + return self.run( + f'down {str(x)}', + f'Descending to {str(x)} cm from the ground \r\n' + ) + logging.warning('tello.down(): Invalid value.') + return 'error' + + def left(self, x: int): + """Sends command to move left x cm""" + logging.debug('Sending command: left()') if x >= 20 and x <= 500: - a = ' '.join(['left', str(x)]) - return self.run(a, ' '.join(['Moving left', str(x), 'cm, keep clear of drone\'s path \r\n'])) - print('\r\nERROR: Parameter must be between 20 and 500') - print('ERROR LOCATION: tello.left()\r\n') + return self.run( + f'left {str(x)}', + f'Moving left {str(x)} cm, keep clear of drone\'s path \r\n' + ) + logging.warning('tello.left(): Invalid value.') + return 'error' + def right(self, x: int): - '''Sends command to move right x cm''' + """Sends command to move right x cm""" + logging.debug('Sending command: right()') if x >= 20 and x <= 500: - a = ' '.join(['right', str(x)]) - return self.run(a, ' '.join(['Moving right', str(x), 'cm, keep clear of drone\'s path \r\n'])) - print('\r\nERROR: Parameter must be between 20 and 500') - print('ERROR LOCATION: tello.right()\r\n') + return self.run( + f'right {str(x)}', + f'Moving right {str(x)} cm, keep clear of drone\'s path \r\n' + ) + logging.warning('tello.right(): Invalid value.') + return 'error' + def forward(self, x: int): - '''Sends command to move forward x cm''' + """Sends command to move forward x cm""" + logging.debug('Sending command: forward()') if x >= 20 and x <= 500: - a = ' '.join(['forward', str(x)]) - return self.run(a, ' '.join(['Moving forward', str(x), 'cm, keep clear of drone\'s path \r\n'])) - print('\r\nERROR: Parameter must be between 20 and 500') - print('ERROR LOCATION: tello.forward()\r\n') - def back(self, x: int ): - '''Sends command to move back x cm''' + return self.run( + f'forward {str(x)}', + f'Moving forward {str(x)} cm, keep clear of drone\'s path \r\n' + ) + logging.warning('tello.forward(): Invalid value.') + return 'error' + + def back(self, x: int): + """Sends command to move back x cm""" + logging.debug('Sending command: back()') if x >= 20 and x <= 500: - a = ' '.join(['back', str(x)]) - return self.run(a, ' '.join(['Moving forward', str(x), 'cm, keep clear of drone\'s path \r\n'])) - print('\r\nERROR: Parameter must be between 20 and 500') - print('ERROR LOCATION: tello.back()\r\n') + return self.run( + f'back {str(x)}', + f'Moving forward {str(x)} cm, keep clear of drone\'s path \r\n' + ) + logging.warning('tello.back(): Invalid value.') + return 'error' + def cw(self, x: int): - '''Sends command to rotate clockwise x degrees''' + """Sends command to rotate clockwise x degrees""" + logging.debug('Sending command: cw()') if x >= 1 and x <= 360: - a = ' '.join(['cw', str(x)]) - return self.run(a, ' '.join(['Rotating clockwise for', str(x), 'degrees \r\n'])) - print('\r\nERROR: Parameter must be between 1 and 360') - print('ERROR LOCATION: tello.cw()\r\n') + return self.run( + f'cw {str(x)}', + f'Rotating clockwise for {str(x)} degrees \r\n' + ) + logging.warning('tello.cw(): Invalid value.') + return 'error' + def ccw(self, x: int): - '''Sends command to rotate counter-clockwise x degrees''' + """Sends command to rotate counter-clockwise x degrees""" + logging.debug('Sending command: ccw()') if x >= 1 and x <= 360: - a = ' '.join(['ccw', str(x)]) - return self.run(a, ' '.join(['Rotating counter-clockwise for', str(x), 'degrees \r\n'])) - print('\r\nERROR: Parameter must be between 1 and 360') - print('ERROR LOCATION: tello.ccw()\r\n') - def flip(self, x: int): - '''Sends command to flip in direction x''' + return self.run( + f'ccw {str(x)}', + f'Rotating counter-clockwise for {str(x)} degrees \r\n' + ) + logging.warning('tello.ccw(): Invalid value.') + return 'error' + + def flip(self, x: str): + """Sends command to flip in direction x""" + logging.debug('Sending command: flip()') if x in ('l', 'r', 'f', 'b'): - a = ' '.join(['flip', x]) - return self.run(a, ' '.join(['Flipping', str(x), ', be careful \r\n'])) - print('\r\nERROR: Parameter must be either f, b, r, or l!') - print('ERROR LOCATION: tello.flip()\r\n') + return self.run( + f'flip {x}', + f'Flipping {x}, be careful \r\n' + ) + logging.warning('tello.flip(): Invalid value.') + return 'error' + def set_speed(self, x: int): - '''Sends command to set speed to x cm/s''' + """Sends command to set speed to x cm/s""" + logging.debug('Sending command: set_speed()') if x >= 1 and x <= 100: - a = ' '.join(['speed', str(x)]) - return self.run(a, ' '.join(['Setting speed to', str(x), 'cm/s \r\n'])) - print('\r\nERROR: Parameter must be between 10 and 100') - print('ERROR LOCATION: tello.setSpeed()\r\n') + return self.run( + f'speed {str(x)}', + f'Setting speed to {str(x)} cm/s \r\n' + ) + logging.warning('tello.set_speed(): Invalid value.') + return 'error' + def set_wifi(self, ssid: str, passw: str): - '''Sends command to set wifi to ssid and passw''' - return self.run(' '.join(['wifi', ssid, passw]), ' '.join(['Setting wifi to', ssid, 'with password', passw, 'then rebooting\r\n'])) + """Sends command to set wifi ssid and passw""" + logging.debug('Sending command: set_wifi()') + logging.debug(f'SSID: {ssid}, PASSW: {passw}') + logging.debug('Please note that you will not be able to connect to the drone if you forget this password!') + return self.run( + f'wifi {ssid}, {passw}', + f'Setting wifi to {ssid}, with password {passw} then rebooting\r\n' + ) + def set_mission_on(self): - '''Sends command to set mission pad detection on''' - return self.run('mon', 'Enabling Mission Pad detection\r\n') + """Sends command to set mission pad detection on""" + logging.debug('Sending command: set_mission_on()') + return self.run( + 'mon', + 'Enabling Mission Pad detection\r\n' + ) + def set_mission_off(self): - '''Sends command to set mission pad detection off''' - return self.run('moff', 'Disabling Mission Pad detection\r\n') + """Sends command to set mission pad detection off""" + logging.debug('Sending command: set_mission_off()') + return self.run( + 'moff', + 'Disabling Mission Pad detection\r\n' + ) + def set_mission_direction(self, x: int): - '''Sends command to set mission pad detection direction to x''' + """Sends command to set mission pad detection direction""" + logging.debug('Sending command: set_mission_direction()') if x >= 0 and x <= 3: - a = ' '.join(['mdirection', str(x)]) - return self.run(a, ' '.join(['Setting Mission Pad Detection to setting', str(x), '\r\n'])) - print('\r\nERROR: Parameter must be between 0 and 3') - print('ERROR LOCATION: tello.setMdircetion()\r\n') + return self.run( + f'mdirection {str(x)}', + f'Setting Mission Pad Detection to setting {str(x)}\r\n') + logging.warning('tello.set_mission_direction(): Invalid value.') + return 'error' # GET Commands def get_speed(self): - '''Sends command to get speed''' - return self.run('speed?', 'Obtaining current speed \r\n') + """Sends command to get speed""" + logging.debug('Sending command: get_speed()') + return self.run( + 'speed?', + 'Obtaining current speed \r\n' + ) + def get_battery(self): - '''Sends command to get battery''' - return self.run('battery?', 'Obtaining battery level \r\n') + """Sends command to get battery percentage""" + logging.debug('Sending command: get_battery()') + return self.run( + 'battery?', + 'Obtaining battery level \r\n' + ) + def get_time(self): - '''Sends command to get flight time''' - return self.run('time?', 'Obtaining current flight time \r\n') + """Sends command to get flight time""" + logging.debug('Sending command: get_time()') + return self.run( + 'time?', + 'Obtaining current flight time \r\n' + ) + def get_wifi(self): - '''Sends command to get wifi info''' - return self.run('wifi?', 'Obtaining WiFi SNR \r\n') + """Sends command to get wifi info""" + logging.debug('Sending command: get_wifi()') + return self.run( + 'wifi?', + 'Obtaining WiFi SNR \r\n' + ) + def get_sdk(self): - '''Sends command to get SDK version''' - return self.run('sdk?', 'Obtaining Tello SDK Version \r\n') + """Sends command to get SDK version""" + logging.debug('Sending command: get_sdk()') + return self.run( + 'sdk?', + 'Obtaining Tello SDK Version \r\n' + ) + def get_sn(self): - '''Sends command to get serial number''' - return self.run('sn?', 'Obtaining Tello serial number \r\n') + """Sends command to get serial number""" + logging.debug('Sending command: get_sn()') + return self.run( + 'sn?', + 'Obtaining Tello serial number \r\n' + ) + # SDK 3.0 GET Commands def get_hardware(self): - '''Sends command to get hardware (RMTT or Tello)''' - return self.run('hardware?', 'Obtaining hardware status \r\n') + """Sends command to get hardware (RMTT or Tello)""" + logging.debug('Sending command: get_hardware()') + return self.run( + 'hardware?', + 'Obtaining hardware status \r\n' + ) + def get_rmtt_wifi_version(self): - '''Sends command to get rmtt wifi version''' - return self.run('wifi?', 'Obtaining RMTT WiFi version \r\n') + """Sends command to get RMTT WiFi version""" + logging.debug('Sending command: get_rmtt_wifi_version()') + return self.run( + 'wifi?', + 'Obtaining RMTT WiFi version \r\n' + ) + def get_ap(self): - '''Sends command to get rmtt ap info''' - return self.run('ap?', 'Obtaining RMTT Access Point SSID and password \r\n') - def get_ssid(self): - '''Sends command to get rmtt ssid info''' - return self.run('ssid?', 'Obtaining RMTT WiFi SSID and password (if any) \r\n') + """Sends command to get RMTT AP info""" + logging.debug('Sending command: get_ap()') + return self.run( + 'ap?', + 'Obtaining RMTT Access Point SSID and password \r\n' + ) + def get_ssid(self): + """Sends command to get RMTT SSID""" + logging.debug('Sending command: get_ssid()') + return self.run( + 'ssid?', + 'Obtaining RMTT WiFi SSID and password (if any) \r\n' + ) # COMPLEX Commands def go(self, x: int, y: int, z: int, s: int): - '''Sends command to move to x y z at speed s''' + """Sends command to move to x y z at speed s""" + logging.debug('Sending command: go()') if 500 >= x >= -500 and 500 >= y >= -500 and 500 >= z >= -500: if 100 >= s >= 10: - a = ' '.join(['go', str(x), str(y), str(z), str(s)]) - return self.run(a, ' '.join(['Going according to parameters coordinates (x, y, z):', str(x), str(y), str(z), 'at the speed of', str(s), 'cm/s\r\n'])) - print('\r\nERROR: Parameter \'s\' needs to be between 10 and 100!') - print('ERROR LOCATION: tello.go()\r\n') - else: - print('\r\nERROR: Parameters x, y, z need to be between 500 and -500!') - print('ERROR LOCATION: tello.go()\r\n') + return self.run( + f'go {str(x)} {str(y)} {str(z)} {str(z)}', + f'Going to coordinates (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n' + ) + logging.warning('tello.go(): Invalid speed.') + return 'error' + logging.warning('tello.go(): Invalid coordinates.') + return 'error' + def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): - '''Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2''' + """Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2""" + logging.debug('Sending command: curve()') if 500 >= x1 >= -500 and 500 >= x2 >= -500 and 500 >= y1 >= -500 and 500 >= y2 >= -500 and 500 >= z1 >= -500 and 500 >= z2 >= -500: if 60 >= s >= 10: - a = ' '.join(['curve', str(x1), str(x2), str(y1), str(y2), str(z1), str(z2), str(s)]) - return self.run(a, ' '.join(['Curving according to parameters (x1, x2, y1, y2, z1, z2):', str(x1), str(x2), str(y1), str(y2), str(z1), str(z2), 'at the speed of', str(s), 'cm/s\r\n'])) - print('\r\nERROR: Parameter \'s\' needs to be between 10 and 60!') - print('ERROR LOCATION: tello.curve()\r\n') - else: - print('\r\nERROR: Parameters x1, x2, y1, y2, z1, z2 need to be between 500 and -500!') - print('ERROR LOCATION: tello.curve()\r\n') + return self.run( + f'curve {str(x1)} {str(y1)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)}', + f'Curving from (x, y, z): {str(x1)} {str(y1)} {str(z1)} to {str(x2)} {str(y2)} {str(z2)} at the speed of', str(s), 'cm/s\r\n' + ) + logging.warning('tello.curve(): Invalid speed.') + return 'error' + logging.warning('tello.curve(): Invalid coordinates.') + return 'error' + def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): - '''Sends command to move to x y z at speed s to mission pad mid''' + """Sends command to move to mission pad x y z at speed s and find mission pad mid""" + logging.debug('Sending command: go_mission_pad()') mid_ok = False for id in self.mids.split(' '): if id == mid: @@ -389,18 +637,20 @@ def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): if 500 >= x >= -500 and 500 >= y >= -500 and 500 >= z >= -500: if 100 >= s >= 10: if mid_ok: - a = ' '.join(['go', str(x), str(y), str(z), str(s), str(mid)]) - return self.run(a, ' '.join(['Going according to parameters coordinates (x, y, z):', str(x), str(y), str(z), 'at the speed of', str(s), 'cm/s\r\n'])) - print('\r\nERROR: Parameter mid needs to be between m1 and m8!') - print('ERROR LOCATION: tello.goMpad()\r\n') - else: - print('\r\nERROR: Parameter \'s\' needs to be between 10 and 100!') - print('ERROR LOCATION: tello.goMpad()\r\n') - else: - print('\r\nERROR: Parameters x, y, z need to be between 500 and -500!') - print('ERROR LOCATION: tello.goMpad()\r\n') + return self.run( + f'go {str(x)} {str(y)} {str(z)} {str(s)} {str(mid)}', + f'Going to (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n' + ) + logging.warning('tello.go_mission_pad(): Invalid mission pad ID.') + return 'error' + logging.warning('tello.go_mission_pad(): Invalid speed.') + return 'error' + logging.warning('tello.go_mission_pad(): Invalid coordinates.') + return 'error' + def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int, mid: str): - '''Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2 to mission pad mid''' + """Sends command to curve from x y z 1 at speed s to x y z 2 and find mission pad mid""" + logging.debug('Sending command: curve_mission_pad()') mid_ok = False for id in self.split(' '): if id == mid: @@ -409,113 +659,154 @@ def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int if 500 >= x1 >= -500 and 500 >= x2 >= -500 and 500 >= y1 >= -500 and 500 >= y2 >= -500 and 500 >= z1 >= -500 and 500 >= z2 >= -500: if 60 >= s >= 10: if mid_ok: - a = ' '.join(['curve', str(x1), str(x2), str(y1), str(y2), str(z1), str(z2), str(s), str(mid)]) - return self.run(a, ' '.join(['Curving according to parameters (x1, x2, y1, y2, z1, z2):', str(x1), str(x2), str(y1), str(y2), str(z1), str(z2), 'at the speed of', str(s), 'cm/s\r\n'])) - print('\r\nERROR: Parameter mid needs to be between m1 and m8!') - print('ERROR LOCATION: tello.curveMpad()\r\n') - else: - print('\r\nERROR: Parameter \'s\' needs to be between 10 and 60!') - print('ERROR LOCATION: tello.curveMpad()\r\n') - else: - print('\r\nERROR: Parameters x1, x2, y1, y2, z1, z2 need to be between 500 and -500!') - print('ERROR LOCATION: tello.curveMpad()\r\n') + return self.run( + f'curve {str(x1)} {str(x2)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)} {str(mid)}', + f'Curving from (x, y, z): {x1} {y1} {z1} to {x2} {y2} {z2} at the speed of {str(s)} cm/s\r\n' + ) + logging.warning('tello.curve_mission_pad(): Invalid mission pad ID.') + return 'error' + logging.warning('tello.curve_mission_pad(): Invalid speed.') + return 'error' + logging.warning('tello.curve_mission_pad(): Invalid coordinates.') + return 'error' + # # SDK 3.0 DISPLAY Commands # def set_light_color(self, r: int, g: int, b: int): - '''Sends command to set the color of the LED''' + """Sends command to set the color of the LED""" + logging.debug('Sending command: set_light_color()') if 255 >= r >= 0 and 255 >= g >= 0 and 255 >= b >= 0: - a = f'EXT led {str(r)} {str(g)} {str(b)}' - return self.run(a, f'Setting RMTT light color to (r, g, b): {str(r)}, {str(g)}, {str(b)}\r\n') - print('\r\nERROR: Parameters r, g, b need to be between 255 and 0!') - print('ERROR LOCATION: tello.set_light_color()\r\n') + return self.run( + f'EXT led {str(r)} {str(g)} {str(b)}', + f'Setting RMTT light color to (r, g, b): {str(r)}, {str(g)}, {str(b)}\r\n' + ) + logging.warning('tello.set_light_color(): Invalid color.') return 'led error' + def set_light_pulse(self, r: int, g: int, b: int, p: float or int): - '''Sends command to set the color and pulse of the LED''' + """Sends command to set the color of the LED and pulse""" + logging.debug('Sending command: set_light_pulse()') if 255 >= r >= 0 and 255 >= g >= 0 and 255 >= b >= 0 and 2.5 >= p >= 0.1: - a = f'EXT led {str(p)} {str(r)} {str(g)} {str(b)}' - return self.run(a, f'Setting RMTT light color to (r, g, b):, {str(r)}, {str(g)}, {str(b)}, with pulse of, {str(p)}, Hz\r\n') - print('\r\nERROR: Parameters r, g, b need to be between 255 and 0!') - print('ERROR LOCATION: tello.set_light_pulse()\r\n') + return self.run( + f'EXT led {str(p)} {str(r)} {str(g)} {str(b)}', + f'Setting RMTT light color to (r, g, b):, {str(r)}, {str(g)}, {str(b)}, with pulse of, {str(p)}, Hz\r\n' + ) + logging.warning('tello.set_light_pulse(): Invalid values.') return 'led error' + def set_light_flash(self, r1: int, g1: int, b1: int, r2: int, g2: int, b2: int, f: float or int): - '''Sends command to set the 2 colors to flash of the LED''' + """Sends command to set the 2 colors of the LED to flash""" + logging.debug('Sending command: set_light_flash()') if 255 >= r1 >= 0 and 255 >= g1 >= 0 and 255 >= b1 >= 0 and 255 >= r2 >= 0 and 255 >= g2 >= 0 and 255 >= b2 >= 0 and 2.5 >= f >= 0.1: - a = f'EXT led {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}' - return self.run(a, f'Setting RMTT light color to (r1, g1, b1): {str(r1)}, {str(g1)}, {str(b1)} and (r2, g2, b2): {str(r2)}, {str(g2)}, {str(b2)} with flash of {str(f)} Hz\r\n') - print('\r\nERROR: Parameters r1, g1, b1, r2, g2, b2 need to be between 255 and 0, f between 0.1 and 10!') - print('ERROR LOCATION: tello.set_light_flash()\r\n') + return self.run( + f'EXT led {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}', + f'Setting RMTT light color to (r, g, b): {str(r1)}, {str(g1)}, {str(b1)} and {str(r2)}, {str(g2)}, {str(b2)} with flash of {str(f)} Hz\r\n' + ) + logging.warning('tello.set_light_flash(): Invalid values.') return 'led error' + def set_display_pattern(self, pattern: str): - '''Sends command to set the display pattern''' + """Sends command to set the display pattern""" + logging.debug('Sending command: set_display_pattern()') if pattern.split('') in ('r', 'b', 'p', '0') and 64 > pattern.length > 1: a = f'EXT mled g {str(pattern)}' - return self.run(a, f'Setting RMTT display pattern to: {str(pattern)} \r\n') - print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 64 characters!') - print('ERROR LOCATION: tello.set_display_pattern()\r\n') + return self.run( + f'EXT mled g {str(pattern)}', + f'Setting RMTT display pattern to: {str(pattern)} \r\n' + ) + logging.warning('tello.set_display_pattern(): Invalid pattern.') return 'mled error' + # # AWAITING TESTING # def set_display_string_direction(self, direction: str, color: str, frame_rate: float or int, pattern: str): - '''Sends command to set the display string direction''' # TO BE CHANGED + """Sends command to set the display string direction""" # TO BE CHANGED + logging.debug('Sending command: set_display_string_direction()') # TO BE CHANGED if direction.split('') in ('l', 'r', 'u', 'd') and color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1 and 70 > pattern.length > 1 and pattern.split('') in ('r', 'b', 'p', '0'): - a = f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}' - return self.run(a, f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)} and frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n') - print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 70 characters, color must contain r, b, or p, direction can contain only u, d, l, r, and frame rate can be a int or float between 0.1 and 10!') - print('ERROR LOCATION: tello.set_display_string_direction()\r\n') + return self.run( + f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}', + f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)}, frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n' + ) + logging.warning('tello.set_display_string_direction(): Invalid values.') # TO BE CHANGED return 'mled error' + # # AWAITING TESTING # def set_display_image_direction(self, direction: str, color: str, frame_rate: float or int, pattern: str): - '''Sends command to set the display image direction''' # TO BE CHANGED + """Sends command to set the display image direction""" # TO BE CHANGED + logging.debug('Sending command: set_display_image_direction()') # TO BE CHANGED if direction.split('') in ('l', 'r', 'u', 'd') and color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1 and 70 > pattern.length > 1 and pattern.split('') in ('r', 'b', 'p', '0'): - a = f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}' - return self.run(a, f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)} and frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n') - print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 70 characters, color must contain r, b, or p, direction can contain only u, d, l, r, and frame rate can be a int or float between 0.1 and 10!') - print('ERROR LOCATION: tello.set_display_image_direction()\r\n') + return self.run( + f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}', + f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)}, frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n' + ) + logging.warning('tello.set_display_image_direction(): Invalid values.') # TO BE CHANGED return 'mled error' + def set_display_ascii_character(self, character: str, color: str): - '''Sends command to display an ascii charachter on the display''' + """Sends command to display ascii character""" + logging.debug('Sending command: set_display_ascii_character()') if character == 'heart' or character == string.printable and color in ('r', 'b', 'p'): - a = f'EXT mled s {str(character)}, {str(color)}' - return self.run(a, f'Displaying ASCII character: {str(character)} with color: {str(color)} \r\n') - print('\r\nERROR: Parameter character needs to be a printable character or "heart", and color must contain r, b, or p!') - print('ERROR LOCATION: tello.set_display_ascii_character()\r\n') + return self.run( + f'EXT mled s {str(character)}, {str(color)}', + f'Displaying ASCII character: {str(character)} with color: {str(color)} \r\n' + ) + logging.warning('tello.set_display_ascii_character(): Invalid values.') return 'mled error' + def set_display_boot(self, pattern: str): - '''Sends command to set the boot animation for the display ''' + """Sends command to set the display boot pattern""" + logging.debug('Sending command: set_display_boot()') if pattern.split('') in ('r', 'b', 'p', '0') and 64 > pattern.length > 1: - a = f'EXT mled sg {str(pattern)}' - return self.run(a, f'Setting RMTT boot display pattern to: {str(pattern)} \r\n') - print('\r\nERROR: Parameter pattern needs to contain only r, b, p and 0, and must be between 1 and 64 characters!') - print('ERROR LOCATION: tello.set_display_boot()\r\n') + return self.run( + f'EXT mled sg {str(pattern)}', + f'Setting RMTT boot display pattern to: {str(pattern)} \r\n' + ) + logging.warning('tello.set_display_boot(): Invalid pattern.') return 'mled error' + def clear_display_boot(self): - '''Sends command to clear boot animation for the display ''' - a = 'EXT mled sc' - return self.run(a, 'Clearing RMTT boot display pattern\r\n') + """Sends command to clear the display boot pattern""" + logging.debug('Sending command: clear_display_boot()') + return self.run( + 'EXT mled sc', + 'Clearing RMTT boot display pattern\r\n' + ) + def set_display_brightness(self, brightness: int): - '''Sends command to set the display brightness''' + """Sends command to set the display brightness""" + logging.debug('Sending command: set_display_brightness()') if 255 >= brightness >= 0: - a = f'EXT mled sl {str(brightness)}' - return self.run(a, f'Setting RMTT display brightness to: {str(brightness)} \r\n') - print('\r\nERROR: Parameter brightness needs to be between 0 and 255!') - print('ERROR LOCATION: tello.set_display_brightness()\r\n') + return self.run( + f'EXT mled sl {str(brightness)}', + f'Setting RMTT display brightness to: {str(brightness)} \r\n' + ) + logging.warning('tello.set_display_brightness(): Invalid brightness.') return 'mled error' + def get_height(self): - '''Sends command to get the height of the drone from ground''' - a = 'EXT tof?' - return self.run(a, 'Getting height...\r\n') + '''Sends command to get the distance of the drone from the floor''' + logging.debug('Sending command: get_height()') + return self.run( + 'EXT tof?', + 'Getting height...\r\n' + ) + def get_rmtt_version(self): - '''Sends command to get the open-source controller (RMTT) version''' - a = 'EXT version?' - return self.run(a, 'Getting RMTT version...\r\n') + '''Sends command to get the RMTT version''' + logging.debug('Sending command: get_rmtt_version()') + return self.run( + 'EXT version?', + 'Getting RMTT version...\r\n' + ) # End command def end(self): - '''Sends end command to Tello''' + """Closes the socket""" + logging.debug('end(): Closing socket') self.sock.close() - print('Exiting...') + logging.debug('end(): Socket closed') return 'ok' diff --git a/telloLive.py b/telloLive.py index a99e0ef..304f9f3 100644 --- a/telloLive.py +++ b/telloLive.py @@ -1,10 +1,7 @@ -# -# Ryze TELLO Live Drone Control Program -# -# -# This is not part of the Tello library/module. +# Support for this has ended. This will no lonegr be updated. +# A new real-time Tello control script is coming soon -import threading +import threading import socket import sys import time @@ -32,7 +29,10 @@ try: - process = subprocess.Popen(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I'], stdout=subprocess.PIPE) + process = subprocess.Popen([ + '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', + '-I' + ], stdout=subprocess.PIPE) out, err = process.communicate() process.wait() wifi_val = {} @@ -54,8 +54,7 @@ print('No errors. \r\n') except subprocess.SubprocessError: print('\r\nSeems like there was an error checking the network.') - print('Aborting script.\r\n') - sys.exit() + print('Continuing.\r\n') print(' Making UDP socket... \r\n') @@ -70,9 +69,10 @@ sock.bind(locaddr) -#Receiving Functionality +# Receiving Functionality def recv(): - while True: + """Receive the response from Tello.""" + while True: try: data, _ = sock.recvfrom(1518) data = data.decode(encoding='utf-8') @@ -84,7 +84,7 @@ def recv(): print('Next time, try writing something valid!') print(data) except Exception: - print ('\nExiting...\n') + print('\nExiting...\n') break @@ -95,12 +95,12 @@ def recv(): print("\r\nTo begin, type", '\033[1m' + 'command' + '\033[0m: \r\n') -#recvThread create +# recvThread create recvThread = threading.Thread(target=recv) recvThread.start() -#Main loop: what happens repeatedly +# Main loop: what happens repeatedly while True: try: msg = input("") @@ -110,7 +110,7 @@ def recv(): # Ending functionality (when typed 'end') if msg == 'end': - print ('...') + print('...') print('Make sure the drone has fully landed! \r\n') endmsg = input("Continue? (y/n)") if endmsg == "y": @@ -181,9 +181,9 @@ def recv(): print('\r\nTo view set, read and hard functions, type \'help set\', \'help read\' or \'help hard\' \r\n\r\n') else: # Send data - msg = msg.encode(encoding="utf-8") + msg = msg.encode(encoding="utf-8") sent = sock.sendto(msg, tello_address) except KeyboardInterrupt: - print ('\n . . .\n') - sock.close() + print('\n . . .\n') + sock.close() break From e9272dae438485c5f2306eb485b88a541880b342 Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Tue, 13 Sep 2022 12:47:20 +0300 Subject: [PATCH 03/18] v2.0.3-alpha New files for pip, reorganized structure, and added license. Install us on pip now: tello-sdk! --- .gitattributes | 2 -- LICENSE.txt | 21 +++++++++++++ README.md | 22 +++++++++----- WRITEHERE.py | 0 setup.cfg | 2 ++ setup.py | 30 +++++++++++++++++++ tello-sdk/__init__.py | 1 + .../guides/.deepsource.toml | 0 {guides => tello-sdk/guides}/COMPLEX_GUIDE.md | 0 {guides => tello-sdk/guides}/README.md | 0 .../guides}/SET&READ_GUIDE.md | 0 tello.py => tello-sdk/tello.py | 21 +++++++------ telloLive.py => tello-sdk/telloLive.py | 0 13 files changed, 79 insertions(+), 20 deletions(-) delete mode 100644 .gitattributes create mode 100644 LICENSE.txt delete mode 100644 WRITEHERE.py create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tello-sdk/__init__.py rename .deepsource.toml => tello-sdk/guides/.deepsource.toml (100%) rename {guides => tello-sdk/guides}/COMPLEX_GUIDE.md (100%) rename {guides => tello-sdk/guides}/README.md (100%) rename {guides => tello-sdk/guides}/SET&READ_GUIDE.md (100%) rename tello.py => tello-sdk/tello.py (97%) rename telloLive.py => tello-sdk/telloLive.py (100%) diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..c0d3a7d --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 ErnGusMik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index e02e87e..7bf3ef2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.0.2 Alpha*
+*2.0.3 Alpha*
SDK 3.0 is **here**! Documentation and testing in progress! ## Requirements: * Python installed on your system or as a VS Code extension @@ -216,29 +216,37 @@ tello.end() ``` ## Version history: -**2.0.2 Alpha** +**2.0.3-alpha** +* Reorganized structure for PyPi +* Added LICENSE.txt (MIT License) +* Added setup.cfg +* Added setup.py and configured for PyPi +* Added tello-sdk/__init__.py +* We're pip installable now! + +**2.0.2-alpha** * Style fixes * Started work on going pip-ready :) * Changed all print to logging (for easier debugging) * Added debugging and tips options to Tello class -**2.0.1 Alpha** +**2.0.1-alpha** * Small fixes -**2.0 Alpha** +**2.0-alpha** * All new Tello SDK 3.0 commands implemented! * Small potential bug/style fixes * This is an Alpha version, so it is **not** stable, by any means! -**1.1.2 Alpha** +**1.1.2-alpha** * Potential bug fixes * Security issue fix * Performance optimizations * Remodel of __init__ function -**1.1 Beta:** +**1.1-beta:** * Implementation of some Tello SDK 3.0 commands * Naming changes * Functions now return the response @@ -246,7 +254,7 @@ tello.end() * V1.1.1: spelling fix -**1.0 Beta:** +**1.0-beta:** * Implement most of Tello SDK 2.0 commands * Documentation started * `tello.run()` command for executing any command straight to the drone. diff --git a/WRITEHERE.py b/WRITEHERE.py deleted file mode 100644 index e69de29..0000000 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..224a779 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[metadata] +description-file = README.md \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..4d89e53 --- /dev/null +++ b/setup.py @@ -0,0 +1,30 @@ +from distutils.core import setup +import email + +setup( + name='tello-sdk', + packages=['tello-sdk'], + version='2.0.3', + license='MIT', + description='Python SDK fro the Tello EDU and RMTT drones, with all commands and more', + author='ErnGusMik', + author_email='ernests.mikuts@gmail.com', + url='https://github.com/ErnGusMik/python-tello', + download_url='', # LINK TO THE TAR.GZ FILE + keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], + install_requires=[ + 'sentry-sdk' + ], + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Build Tools', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + ] +) \ No newline at end of file diff --git a/tello-sdk/__init__.py b/tello-sdk/__init__.py new file mode 100644 index 0000000..1de6e64 --- /dev/null +++ b/tello-sdk/__init__.py @@ -0,0 +1 @@ +from tello import Tello \ No newline at end of file diff --git a/.deepsource.toml b/tello-sdk/guides/.deepsource.toml similarity index 100% rename from .deepsource.toml rename to tello-sdk/guides/.deepsource.toml diff --git a/guides/COMPLEX_GUIDE.md b/tello-sdk/guides/COMPLEX_GUIDE.md similarity index 100% rename from guides/COMPLEX_GUIDE.md rename to tello-sdk/guides/COMPLEX_GUIDE.md diff --git a/guides/README.md b/tello-sdk/guides/README.md similarity index 100% rename from guides/README.md rename to tello-sdk/guides/README.md diff --git a/guides/SET&READ_GUIDE.md b/tello-sdk/guides/SET&READ_GUIDE.md similarity index 100% rename from guides/SET&READ_GUIDE.md rename to tello-sdk/guides/SET&READ_GUIDE.md diff --git a/tello.py b/tello-sdk/tello.py similarity index 97% rename from tello.py rename to tello-sdk/tello.py index 94a3b9e..7f96c4c 100644 --- a/tello.py +++ b/tello-sdk/tello.py @@ -27,7 +27,6 @@ class Tello(): """Class for info commands to the Tello or RMTT drones""" - def __init__(self, log_in_console: bool = True, tips: bool = True): """Checks network name, creates UDP socket and prints starting info to user""" # Configure logging @@ -76,7 +75,7 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): logging.info(' Drone Script ') logging.info('--------------------------------------') - logging.debug(f'Current port for UDP connection: {str(port)}') + logging.debug('Current port for UDP connection: %s', str(port)) logging.info(' Checking network... \r\n') time.sleep(0.5) @@ -110,7 +109,7 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): val = val.strip() wifi_val = val if 'TELLO-' not in wifi_val or 'RMTT-' not in wifi_val: - logging.debug(f'Network detected: {wifi_val}') + logging.debug('Network detected: %s', wifi_val) logging.warning('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') else: logging.debug('Required network detected:', wifi_val) @@ -127,7 +126,7 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): self.tello_address = ('192.168.10.1', 8889) self.sock.bind(locaddr) logging.debug('Socket created.') - logging.debug(f'Socket bound to: {str(locaddr)}') + logging.debug('Socket bound to: %s', str(locaddr)) self.recvThread = threading.Thread(target=self.receive) self.recvThread.start() @@ -165,7 +164,7 @@ def run(self, command: str, message: str = "No tips available for this command " if self.abort is False: response = self.response.decode(encoding='utf-8') self.response = None - logging.debug(f'Response to previous command: {response}') + logging.debug('Response to previous command: %s', response) return response return 'error' @@ -234,7 +233,7 @@ def ap(self, ssid: str, password: str): ) def set_wifi_channel(self, channel: int): - '''Sends command to set the WiFi channel''' + """Sends command to set the WiFi channel""" logging.debug('Sending command: set_wifi_channel()') return self.run( f'wifi {channel}', @@ -250,7 +249,7 @@ def set_port(self, info_port: int, video_port: int): 'Setting new ports for status and video\r\n' ) if ports == 'ok': - logging.info(f'New ports set by client: {info_port} and {video_port}') + logging.info('New ports set by client: %s and %s', info_port, video_port) self.info_port = info_port self.tello_address = ('192.168.10.1', info_port) # @@ -358,7 +357,7 @@ def emergency(self, reason='No reason provided'): 'Emergency stop. Attempting to stop motors.\r\n' ) logging.critical('Emergency stop. Exiting script.') - logging.debug(f'Emergency stop due to: {reason}. Unable to continue due to motor stop. Exiting.') + logging.debug('Emergency stop due to: %s. Unable to continue due to motor stop. Exiting.', reason) sys.exit() def stop_movement(self): @@ -482,7 +481,7 @@ def set_speed(self, x: int): def set_wifi(self, ssid: str, passw: str): """Sends command to set wifi ssid and passw""" logging.debug('Sending command: set_wifi()') - logging.debug(f'SSID: {ssid}, PASSW: {passw}') + logging.info('SSID: %s, PASSWORD: %s', ssid, passw) logging.debug('Please note that you will not be able to connect to the drone if you forget this password!') return self.run( f'wifi {ssid}, {passw}', @@ -788,7 +787,7 @@ def set_display_brightness(self, brightness: int): return 'mled error' def get_height(self): - '''Sends command to get the distance of the drone from the floor''' + """Sends command to get the distance of the drone from the floor""" logging.debug('Sending command: get_height()') return self.run( 'EXT tof?', @@ -796,7 +795,7 @@ def get_height(self): ) def get_rmtt_version(self): - '''Sends command to get the RMTT version''' + """Sends command to get the RMTT version""" logging.debug('Sending command: get_rmtt_version()') return self.run( 'EXT version?', diff --git a/telloLive.py b/tello-sdk/telloLive.py similarity index 100% rename from telloLive.py rename to tello-sdk/telloLive.py From 57a4d03d3910855dacc5ee9718b021d2c727952b Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Tue, 13 Sep 2022 12:51:09 +0300 Subject: [PATCH 04/18] v2.0.3-alpha Added download-link --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4d89e53..ea7d425 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ author='ErnGusMik', author_email='ernests.mikuts@gmail.com', url='https://github.com/ErnGusMik/python-tello', - download_url='', # LINK TO THE TAR.GZ FILE + download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.0.3-alpha.tar.gz', keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], install_requires=[ 'sentry-sdk' From 2f3b9a2be257e12a260525219f4ed130bc779876 Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:10:11 +0300 Subject: [PATCH 05/18] v2.0.4-alpha Readded .deepsource.toml --- .../.deepsource.toml => .deepsource.toml | 0 README.md | 6 +- setup.py | 4 +- tello-sdk/guides/COMPLEX_GUIDE.md | 72 ------------ tello-sdk/guides/README.md | 12 -- tello-sdk/guides/SET&READ_GUIDE.md | 109 ------------------ 6 files changed, 7 insertions(+), 196 deletions(-) rename tello-sdk/guides/.deepsource.toml => .deepsource.toml (100%) delete mode 100644 tello-sdk/guides/COMPLEX_GUIDE.md delete mode 100644 tello-sdk/guides/README.md delete mode 100644 tello-sdk/guides/SET&READ_GUIDE.md diff --git a/tello-sdk/guides/.deepsource.toml b/.deepsource.toml similarity index 100% rename from tello-sdk/guides/.deepsource.toml rename to .deepsource.toml diff --git a/README.md b/README.md index 7bf3ef2..124ddaa 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.0.3 Alpha*
+*2.0.4 Alpha*
SDK 3.0 is **here**! Documentation and testing in progress! ## Requirements: * Python installed on your system or as a VS Code extension @@ -216,6 +216,10 @@ tello.end() ``` ## Version history: +**2.0.4-alpha** +* Readded .deepsource.toml +* Hopefully fixed pip 'No Description provided' issue + **2.0.3-alpha** * Reorganized structure for PyPi * Added LICENSE.txt (MIT License) diff --git a/setup.py b/setup.py index ea7d425..f6e5638 100644 --- a/setup.py +++ b/setup.py @@ -4,13 +4,13 @@ setup( name='tello-sdk', packages=['tello-sdk'], - version='2.0.3', + version='2.0.4-alpha', license='MIT', description='Python SDK fro the Tello EDU and RMTT drones, with all commands and more', author='ErnGusMik', author_email='ernests.mikuts@gmail.com', url='https://github.com/ErnGusMik/python-tello', - download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.0.3-alpha.tar.gz', + download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.0.4-alpha.tar.gz', keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], install_requires=[ 'sentry-sdk' diff --git a/tello-sdk/guides/COMPLEX_GUIDE.md b/tello-sdk/guides/COMPLEX_GUIDE.md deleted file mode 100644 index ecc5b59..0000000 --- a/tello-sdk/guides/COMPLEX_GUIDE.md +++ /dev/null @@ -1,72 +0,0 @@ -# Python Tello -This is a library for easy usage of the Ryze Tello drone education edition. -## Requirements: -* Python installed on your system or as a VS Code extension -* Ryze Tello EDU Edition (get one [here](https://www.ryzerobotics.com/tello-edu)) -* This package - -To see the Quickstart guide, see the [README.md file](README.md) -#### Be Cautious when using these functions. They can become confusing very quickly! - -## COMPLEX Functions - -### tello.go(x, y, z, s) -Goes to *x y z* location at speeed *s*.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Distance to go left-right in cm. Allowed values: -500-500 -* y: Integer. Distance to go forwards-backwards in cm. Allowed values: -500-500 -* z: Integer. Distance to go up-down in cm. Allowed values: -500-500 -* s: Integer. Speed. Allowed values: 10-100 -Example: -```python -tello.go(10, 50, 10, 50) # Goes 10 cm right, 50 cm forwards, 10 cm up at the speed of 50 cm/s -``` - -### tello.go_mission_pad(x, y, z, s, mid) -Goes to *x y z* location at speeed *s*.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Distance to go left-right in cm. Allowed values: -500-500 -* y: Integer. Distance to go forwards-backwards in cm. Allowed values: -500-500 -* z: Integer. Distance to go up-down in cm. Allowed values: -500-500 -* s: Integer. Speed. Allowed values: 10-100 -* mid: String. Mission Pad ID. Allowed values: `'m1'`, `'m2'`, `'m3'`, `'m4'`, `'m5'`, `'m6'`, `'m7'`, `'m8'` -Example: -```python -tello.go(100, 40, 5, 50, m1) # Goes 100 cm right, 40 cm forwards, 50 cm up from Mission Pad 1 at the speed of 50 cm/s -``` - -### tello.curve(x1, x2, y1, y2, z1, z2, s) -Curve to the *x2 y2 z2* location, curving through the *x1 y1 z1* location at speeed *s*..
-**Not always works. Use at own risk!**
-Possible responses: `ok` / `error`
-Parameters: -* x1: Integer. Distance to go left-right in cm. Allowed values: -500-500 -* x2: Integer. Distance to go left-right in cm. Allowed values: -500-500 -* y1: Integer. Distance to go forwards-backwards in cm. Allowed values: -500-500 -* y2: Integer. Distance to go forwards-backwards in cm. Allowed values: -500-500 -* z1: Integer. Distance to go up-down in cm. Allowed values: -500-500 -* z2: Integer. Distance to go up-down in cm. Allowed values: -500-500 -Example: -```python -tello.curveMpad(20, 35, 47, 25, 9, 200, 40) # Curves to x=35 y=25 z=200 through x=20 y=47 z=9 at speed 40 cm/s -``` - -### tello.curve_mission_pad(x1, x2, y1, y2, z1, z2, s, mid) -Curve to the *x2 y2 z2* location, curving through the *x1 y1 z1* location at speeed *s* from the *mid* coordinates.
-**Not always works. Use at own risk!**
-Possible responses: `ok` / `error`
-Parameters: -* x1: Integer. Distance to go left-right in cm. Allowed values: -500-500 -* x2: Integer. Distance to go left-right in cm. Allowed values: -500-500 -* y1: Integer. Distance to go forwards-backwards in cm. Allowed values: -500-500 -* y2: Integer. Distance to go forwards-backwards in cm. Allowed values: -500-500 -* z1: Integer. Distance to go up-down in cm. Allowed values: -500-500 -* z2: Integer. Distance to go up-down in cm. Allowed values: -500-500 -* s: Integer. Speed. Allowed values: 10-60 -* mid: String. Mission Pad ID. Allowed values: `'m1'`, `'m2'`, `'m3'`, `'m4'`, `'m5'`, `'m6'`, `'m7'`, `'m8'` -Example: -```python -tello.curveMpad(100, 30, 40, 55, 5, 50, 30, m1) # Curves to x=30 y=55 z=50 through x=100 y=40 z=5 from Mission Pad m1 at speed 30 cm/s -``` diff --git a/tello-sdk/guides/README.md b/tello-sdk/guides/README.md deleted file mode 100644 index 0ffcbf1..0000000 --- a/tello-sdk/guides/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Python Tello -This is a library for easy usage of the Ryze Tello drone education edition. -## Frequently Asked Questions -If you have any other questions, please make a GitHub issue, and I will try to answer it. - -### What errors are there? -Errors include: -* Unknown command: {command} -- this command is not known. -* error Run timeout -- timeout for the command (eg. could not find mission pad). -* error Motor stop -- motors have stopped; turn them on first. -* error -- an error executing the command has happened. -* You need to take off first! -- take off to execute this command. diff --git a/tello-sdk/guides/SET&READ_GUIDE.md b/tello-sdk/guides/SET&READ_GUIDE.md deleted file mode 100644 index d57eba9..0000000 --- a/tello-sdk/guides/SET&READ_GUIDE.md +++ /dev/null @@ -1,109 +0,0 @@ -# Python Tello -This is a library for easy usage of the Ryze Tello drone education edition. - -## Requirements: -* Python installed on your system or as a VS Code extension -* Ryze Tello EDU Edition (get one [here](https://www.ryzerobotics.com/tello-edu)) -* This package - -To see the Quickstart guide, see the [README.md file](README.md) -## Set & Read Functions - -### SET Functions - -### tello.set_speed(x) -Sets speed to *x* cm/s.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Speed in cm/s. Allowed values: 10-100
-Example: -```python -tello.setSpeed(50) # Sets speed to 50 cm/s -``` - -### tello.set_wifi(ssid, passw) -Sets WiFi SSID to *ssis* and password to *passw*.
-Possible responses: `ok` / `error`
-Parameters: -* ssid: String. New SSID for WiFi. Allowed values: any string
-* passw: String. New password for WiFi. Allowed values: any string
-Example: -```python -tello.setWifi('TELLO-XYZ', '1234567') # Sets WiFi SSID to TELLO-XYZ and password to 1234567 -``` - -### tello.set_mission_on() -Sets Mission Pad detection to on.
-Possible responses: `ok` / `error`
-Example: -```python -tello.setMon() # Turns M. Pad detection on -``` - -### tello.set_mission_off() -Sets Mission pad detection to off.
-Possible responses: `ok` / `error`
-Example: -```python -tello.setMoff() # Turns M. Pad detection off -``` - -### tello.set_mission_direction(x) -Sets Mission Pad detection direction(s).
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Sets detection direction. Allowed values: `0` (downward detection), `1` (forward detection), `2` (downward and forward detection)
-Example: -```python -tello.setMdirection(1) # Mission Pad detection direction: forward only. -``` - -## GET functions - -### tello.get_speed() -Gets current speed
-Possible responses: `10-100`
-Example: -```python -tello.getSpeed() # Gets speed -``` - -### tello.get_battery() -Gets current battery percentage
-Possible responses: `0-100`
-Example: -```python -tello.getBattery() # Gets battery percentage -``` - -### tello.get_time() -Gets current flight time
-Possible responses: `"time"`
-Example: -```python -tello.getTime() # Gets flight time -``` - -### tello.get_wifi() -Gets current WiFi SNR
-Possible responses: `"snr"`
-Example: -```python -tello.getWifi() # Gets WiFi SNR -``` - -### tello.get_sdk() -Gets current SDK version
-Possible responses: `"SDK version"`
-Example: -```python -tello.getSDK() # Gets SDK version -``` - -### tello.get_sn() -Gets Tello serial number
-Possible responses: `"sn"`
-Example: -```python -tello.getSN() # Gets serial number -``` From 037ed8247cb25c167352c6ec3307de03fe7d8124 Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:19:15 +0300 Subject: [PATCH 06/18] v2.0.5-alpha --- README.md | 6 +++++- setup.py | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 124ddaa..13d3849 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.0.4 Alpha*
+*2.0.5 Alpha*
SDK 3.0 is **here**! Documentation and testing in progress! ## Requirements: * Python installed on your system or as a VS Code extension @@ -216,6 +216,10 @@ tello.end() ``` ## Version history: +**2.0.5-alpha** +* setup.py changes +* Re-releasing on pip + **2.0.4-alpha** * Readded .deepsource.toml * Hopefully fixed pip 'No Description provided' issue diff --git a/setup.py b/setup.py index f6e5638..eaddb0a 100644 --- a/setup.py +++ b/setup.py @@ -15,6 +15,7 @@ install_requires=[ 'sentry-sdk' ], + long_description='README.md', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', From ada847ddab48551dd94417766ee23644473f48a8 Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Thu, 15 Sep 2022 18:00:09 +0300 Subject: [PATCH 07/18] v2.1.0-alpha Tested all new EXT commands and most other SKD 3.0 commands. Minor changes to setup.py and deepsource.toml. --- .deepsource.toml | 3 +- README.md | 11 ++- setup.py | 9 +-- tello-sdk/__init__.py | 2 +- tello-sdk/tello.py | 152 +++++++++++++++++++++++------------------ tello-sdk/telloLive.py | 2 +- 6 files changed, 104 insertions(+), 75 deletions(-) diff --git a/.deepsource.toml b/.deepsource.toml index aebeb0f..6f6d730 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -5,4 +5,5 @@ name = "python" enabled = true [analyzers.meta] - runtime_version = "3.x.x" \ No newline at end of file + runtime_version = "3.x.x" + max_line_length = 100 \ No newline at end of file diff --git a/README.md b/README.md index 13d3849..7507f35 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.0.5 Alpha*
-SDK 3.0 is **here**! Documentation and testing in progress! +*2.1.0 Alpha*
+SDK 3.0 is **here** and **tested**! Documentation in progress! ## Requirements: * Python installed on your system or as a VS Code extension * Ryze Tello EDU Edition (get one [here](https://www.ryzerobotics.com/tello-edu)) @@ -216,6 +216,13 @@ tello.end() ``` ## Version history: +**2.1.0-alpha** +* Tested all new EXT commands +* Tested most other new commands +* setup.py changes (long-description) +* deepsource.toml changes (max-line-limt: 100) +* tello.set_display_ascii_character() is still being tested. + **2.0.5-alpha** * setup.py changes * Re-releasing on pip diff --git a/setup.py b/setup.py index eaddb0a..3fd7424 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,9 @@ -from distutils.core import setup -import email +from setuptools import setup, find_packages +from pathlib import Path setup( name='tello-sdk', - packages=['tello-sdk'], + packages=find_packages('tello-sdk'), version='2.0.4-alpha', license='MIT', description='Python SDK fro the Tello EDU and RMTT drones, with all commands and more', @@ -16,6 +16,7 @@ 'sentry-sdk' ], long_description='README.md', + long_description_content_type='text/markdown', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', @@ -28,4 +29,4 @@ 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', ] -) \ No newline at end of file +) diff --git a/tello-sdk/__init__.py b/tello-sdk/__init__.py index 1de6e64..a69443c 100644 --- a/tello-sdk/__init__.py +++ b/tello-sdk/__init__.py @@ -1 +1 @@ -from tello import Tello \ No newline at end of file +from tello import Tello diff --git a/tello-sdk/tello.py b/tello-sdk/tello.py index 7f96c4c..9a8b1a1 100644 --- a/tello-sdk/tello.py +++ b/tello-sdk/tello.py @@ -11,7 +11,6 @@ import logging # Initialize Sentry (error catching) -# We will be able to see the name of your computer, the error, and the line of code that caused it. # Delete the following 4 lines to opt out # More: sentry.io @@ -58,6 +57,8 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): self.response = None self.sent = None self.ip = None + self.info_port = 8889 + self.video_port = 11111 # Set variables for connection to drone host = '' @@ -105,14 +106,14 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): wifi_val = 'Not connected' for line in out.decode('utf-8').split('\n'): if "SSID: " in line: - key, val = line.split(': ') + _, val = line.split(': ') val = val.strip() wifi_val = val if 'TELLO-' not in wifi_val or 'RMTT-' not in wifi_val: logging.debug('Network detected: %s', wifi_val) logging.warning('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') else: - logging.debug('Required network detected:', wifi_val) + logging.debug('Required network detected: %s', wifi_val) else: logging.warning('Could not determine network.') logging.warning('Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks.') @@ -171,7 +172,6 @@ def run(self, command: str, message: str = "No tips available for this command " def _set_abort(self): """Sets the abort variable to True""" self.abort = True - return None # SDK 3.0 Commands def throw_fly(self): @@ -371,7 +371,7 @@ def stop_movement(self): def up(self, x: int): """Sends command to move up x cm""" logging.debug('Sending command: up()') - if x >= 20 and x <= 500: + if 20 <= x <= 500: return self.run( f'up {str(x)}', f'Ascending to {str(x)} cm from the ground \r\n' @@ -382,7 +382,7 @@ def up(self, x: int): def down(self, x: int): """Sends command to move down x cm""" logging.debug('Sending command: down()') - if x >= 20 and x <= 500: + if 20 <= x <= 500: return self.run( f'down {str(x)}', f'Descending to {str(x)} cm from the ground \r\n' @@ -390,10 +390,10 @@ def down(self, x: int): logging.warning('tello.down(): Invalid value.') return 'error' - def left(self, x: int): + def left(self, x: int): """Sends command to move left x cm""" logging.debug('Sending command: left()') - if x >= 20 and x <= 500: + if 20 <= x <= 500: return self.run( f'left {str(x)}', f'Moving left {str(x)} cm, keep clear of drone\'s path \r\n' @@ -404,7 +404,7 @@ def left(self, x: int): def right(self, x: int): """Sends command to move right x cm""" logging.debug('Sending command: right()') - if x >= 20 and x <= 500: + if 20 <= x <= 500: return self.run( f'right {str(x)}', f'Moving right {str(x)} cm, keep clear of drone\'s path \r\n' @@ -415,7 +415,7 @@ def right(self, x: int): def forward(self, x: int): """Sends command to move forward x cm""" logging.debug('Sending command: forward()') - if x >= 20 and x <= 500: + if 20 <= x <= 500: return self.run( f'forward {str(x)}', f'Moving forward {str(x)} cm, keep clear of drone\'s path \r\n' @@ -426,7 +426,7 @@ def forward(self, x: int): def back(self, x: int): """Sends command to move back x cm""" logging.debug('Sending command: back()') - if x >= 20 and x <= 500: + if 20 <= x <= 500: return self.run( f'back {str(x)}', f'Moving forward {str(x)} cm, keep clear of drone\'s path \r\n' @@ -437,7 +437,7 @@ def back(self, x: int): def cw(self, x: int): """Sends command to rotate clockwise x degrees""" logging.debug('Sending command: cw()') - if x >= 1 and x <= 360: + if 1 <= x <= 360: return self.run( f'cw {str(x)}', f'Rotating clockwise for {str(x)} degrees \r\n' @@ -448,7 +448,7 @@ def cw(self, x: int): def ccw(self, x: int): """Sends command to rotate counter-clockwise x degrees""" logging.debug('Sending command: ccw()') - if x >= 1 and x <= 360: + if 1 <= x <= 360: return self.run( f'ccw {str(x)}', f'Rotating counter-clockwise for {str(x)} degrees \r\n' @@ -610,7 +610,7 @@ def go(self, x: int, y: int, z: int, s: int): return 'error' logging.warning('tello.go(): Invalid coordinates.') return 'error' - + def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): """Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2""" logging.debug('Sending command: curve()') @@ -626,7 +626,7 @@ def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): return 'error' def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): - """Sends command to move to mission pad x y z at speed s and find mission pad mid""" + """Sends command to move to mission pad x y z at speed s and find Mpad mid""" logging.debug('Sending command: go_mission_pad()') mid_ok = False for id in self.mids.split(' '): @@ -648,7 +648,7 @@ def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): return 'error' def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int, mid: str): - """Sends command to curve from x y z 1 at speed s to x y z 2 and find mission pad mid""" + """Sends command to curve from x y z 1 at speed s to x y z 2 and find Mpad mid""" logging.debug('Sending command: curve_mission_pad()') mid_ok = False for id in self.split(' '): @@ -669,9 +669,15 @@ def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int logging.warning('tello.curve_mission_pad(): Invalid coordinates.') return 'error' - # # SDK 3.0 DISPLAY Commands - # + def set_light_off(self): # TO TEST + """Sends command to turn off the lights""" + logging.debug('Sending command: set_light_off()') + return self.run( + 'EXT led 0 0 0', + 'Turning off the big light\r\n' + ) + def set_light_color(self, r: int, g: int, b: int): """Sends command to set the color of the LED""" logging.debug('Sending command: set_light_color()') @@ -688,8 +694,8 @@ def set_light_pulse(self, r: int, g: int, b: int, p: float or int): logging.debug('Sending command: set_light_pulse()') if 255 >= r >= 0 and 255 >= g >= 0 and 255 >= b >= 0 and 2.5 >= p >= 0.1: return self.run( - f'EXT led {str(p)} {str(r)} {str(g)} {str(b)}', - f'Setting RMTT light color to (r, g, b):, {str(r)}, {str(g)}, {str(b)}, with pulse of, {str(p)}, Hz\r\n' + f'EXT led br {str(p)} {str(r)} {str(g)} {str(b)}', + f'Setting RMTT light color to (r, g, b):, {str(r)}, {str(g)}, {str(b)}, with pulse of, {str(p)} Hz\r\n' ) logging.warning('tello.set_light_pulse(): Invalid values.') return 'led error' @@ -699,73 +705,87 @@ def set_light_flash(self, r1: int, g1: int, b1: int, r2: int, g2: int, b2: int, logging.debug('Sending command: set_light_flash()') if 255 >= r1 >= 0 and 255 >= g1 >= 0 and 255 >= b1 >= 0 and 255 >= r2 >= 0 and 255 >= g2 >= 0 and 255 >= b2 >= 0 and 2.5 >= f >= 0.1: return self.run( - f'EXT led {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}', + f'EXT led bl {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}', f'Setting RMTT light color to (r, g, b): {str(r1)}, {str(g1)}, {str(b1)} and {str(r2)}, {str(g2)}, {str(b2)} with flash of {str(f)} Hz\r\n' ) logging.warning('tello.set_light_flash(): Invalid values.') return 'led error' - def set_display_pattern(self, pattern: str): + def set_display_pattern(self, pattern: str = '0'): """Sends command to set the display pattern""" logging.debug('Sending command: set_display_pattern()') - if pattern.split('') in ('r', 'b', 'p', '0') and 64 > pattern.length > 1: - a = f'EXT mled g {str(pattern)}' - return self.run( - f'EXT mled g {str(pattern)}', - f'Setting RMTT display pattern to: {str(pattern)} \r\n' - ) - logging.warning('tello.set_display_pattern(): Invalid pattern.') - return 'mled error' - - # - # AWAITING TESTING - # - def set_display_string_direction(self, direction: str, color: str, frame_rate: float or int, pattern: str): - """Sends command to set the display string direction""" # TO BE CHANGED - logging.debug('Sending command: set_display_string_direction()') # TO BE CHANGED - if direction.split('') in ('l', 'r', 'u', 'd') and color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1 and 70 > pattern.length > 1 and pattern.split('') in ('r', 'b', 'p', '0'): + for char in pattern: + if char not in 'rbp0': + logging.warning('tello.set_display_pattern(): Invalid pattern.') + return 'matrix error' + return self.run( + f'EXT mled g {str(pattern)}', + f'Setting RMTT display pattern to: {str(pattern)} \r\n' + ) + + def set_display_blank(self): # TO TEST + """Sends command to make the display blank""" + logging.debug('Sending command: set_display_off()') + return self.run( + 'EXT mled g 0000000000000000000000000000000000000000000000000000000000000000', + 'Turning off the display\r\n' + ) + def set_display_string(self, direction: str, color: str, frame_rate: float or int, string: str): + """Sends command to show a string on the display""" + logging.debug('Sending command: set_display_string()') + for char in direction: + if char not in 'lrud': + logging.warning('tello.set_display_string(): Invalid direction.') + return 'matrix error' + if color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1: return self.run( - f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}', - f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)}, frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n' + f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(string)}', + f'Showing the string: {str(string)} with color: {str(color)}, frame rate (Hz): {str(frame_rate)} and in the diretion: {str(direction)} on the RMTT display \r\n' ) - logging.warning('tello.set_display_string_direction(): Invalid values.') # TO BE CHANGED - return 'mled error' - - # - # AWAITING TESTING - # - def set_display_image_direction(self, direction: str, color: str, frame_rate: float or int, pattern: str): - """Sends command to set the display image direction""" # TO BE CHANGED - logging.debug('Sending command: set_display_image_direction()') # TO BE CHANGED - if direction.split('') in ('l', 'r', 'u', 'd') and color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1 and 70 > pattern.length > 1 and pattern.split('') in ('r', 'b', 'p', '0'): + logging.warning('tello.set_display_string(): Invalid values.') + return 'matrix error' + + def set_display_moving_image(self, direction: str, color: str, frame_rate: float or int, pattern: str): + """Sends command to show a moving image on the display""" + logging.debug('Sending command: set_display_moving_image()') + for char in direction: + if char not in 'lrud': + logging.warning('tello.set_display_moving_image(): Invalid direction.') + return 'matrix error' + for char in pattern: + if char not in 'rbp0': + logging.warning('tello.set_display_moving_image(): Invalid pattern.') + return 'matrix error' + if color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1: return self.run( - f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(pattern)}', - f'Setting RMTT string display direction to: {str(direction)} with color: {str(color)}, frame rate: {str(frame_rate)} and pattern: {str(pattern)} \r\n' + f'EXT mled {str(direction)} g {str(frame_rate)} {str(pattern)}', + f'Showing a moving image on the RMTT display in the direction: {str(direction)} with color: {str(color)}, frame rate (Hz): {str(frame_rate)} and pattern: {str(pattern)} \r\n' ) - logging.warning('tello.set_display_image_direction(): Invalid values.') # TO BE CHANGED - return 'mled error' + logging.warning('tello.set_display_moving_image(): Invalid values.') + return 'matrix error' - def set_display_ascii_character(self, character: str, color: str): + def set_display_ascii_character(self, character: str, color: str): # TEST """Sends command to display ascii character""" logging.debug('Sending command: set_display_ascii_character()') - if character == 'heart' or character == string.printable and color in ('r', 'b', 'p'): + if character == 'heart' or character.encode('ascii') and color in ('r', 'b', 'p'): return self.run( - f'EXT mled s {str(character)}, {str(color)}', + f'EXT mled s {str(color)} {str(character.encode("ascii"))}', # TEST f'Displaying ASCII character: {str(character)} with color: {str(color)} \r\n' ) logging.warning('tello.set_display_ascii_character(): Invalid values.') - return 'mled error' + return 'matrix error' def set_display_boot(self, pattern: str): """Sends command to set the display boot pattern""" logging.debug('Sending command: set_display_boot()') - if pattern.split('') in ('r', 'b', 'p', '0') and 64 > pattern.length > 1: - return self.run( - f'EXT mled sg {str(pattern)}', - f'Setting RMTT boot display pattern to: {str(pattern)} \r\n' - ) - logging.warning('tello.set_display_boot(): Invalid pattern.') - return 'mled error' + for char in pattern: + if char not in 'rbp0': + logging.warning('tello.set_display_boot(): Invalid pattern.') + return 'error' + return self.run( + f'EXT mled sg {str(pattern)}', + f'Setting RMTT boot display pattern to: {str(pattern)} \r\n' + ) def clear_display_boot(self): """Sends command to clear the display boot pattern""" @@ -784,7 +804,7 @@ def set_display_brightness(self, brightness: int): f'Setting RMTT display brightness to: {str(brightness)} \r\n' ) logging.warning('tello.set_display_brightness(): Invalid brightness.') - return 'mled error' + return 'matrix error' def get_height(self): """Sends command to get the distance of the drone from the floor""" diff --git a/tello-sdk/telloLive.py b/tello-sdk/telloLive.py index 304f9f3..67c5339 100644 --- a/tello-sdk/telloLive.py +++ b/tello-sdk/telloLive.py @@ -106,7 +106,7 @@ def recv(): msg = input("") if not msg: - break + break # Ending functionality (when typed 'end') if msg == 'end': From ed219af8d295a820ac992034454babed3250bed2 Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Sun, 18 Sep 2022 19:45:59 +0300 Subject: [PATCH 08/18] v2.2.0-alpha Changed some function names, started official docs (GitHub Wiki), created MANIFEST.in. --- LICENSE.txt => LICENCE | 0 MANIFEST.in | 1 + setup.cfg | 2 - setup.py | 13 +++--- {tello-sdk => tello_sdk}/__init__.py | 0 {tello-sdk => tello_sdk}/tello.py | 62 +++++++++++++-------------- {tello-sdk => tello_sdk}/telloLive.py | 0 7 files changed, 39 insertions(+), 39 deletions(-) rename LICENSE.txt => LICENCE (100%) create mode 100644 MANIFEST.in delete mode 100644 setup.cfg rename {tello-sdk => tello_sdk}/__init__.py (100%) rename {tello-sdk => tello_sdk}/tello.py (95%) rename {tello-sdk => tello_sdk}/telloLive.py (100%) diff --git a/LICENSE.txt b/LICENCE similarity index 100% rename from LICENSE.txt rename to LICENCE diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..4bf4483 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include README.md \ No newline at end of file diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 224a779..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[metadata] -description-file = README.md \ No newline at end of file diff --git a/setup.py b/setup.py index 3fd7424..83c6902 100644 --- a/setup.py +++ b/setup.py @@ -1,21 +1,24 @@ from setuptools import setup, find_packages -from pathlib import Path + +def readme(): + with open('README.md') as f: + return f.read() setup( name='tello-sdk', - packages=find_packages('tello-sdk'), - version='2.0.4-alpha', + packages=find_packages('tello_sdk'), + version='2.1.0', license='MIT', description='Python SDK fro the Tello EDU and RMTT drones, with all commands and more', author='ErnGusMik', author_email='ernests.mikuts@gmail.com', url='https://github.com/ErnGusMik/python-tello', - download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.0.4-alpha.tar.gz', + download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.1.0-alpha.tar.gz', keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], install_requires=[ 'sentry-sdk' ], - long_description='README.md', + long_description=readme(), long_description_content_type='text/markdown', classifiers=[ 'Development Status :: 3 - Alpha', diff --git a/tello-sdk/__init__.py b/tello_sdk/__init__.py similarity index 100% rename from tello-sdk/__init__.py rename to tello_sdk/__init__.py diff --git a/tello-sdk/tello.py b/tello_sdk/tello.py similarity index 95% rename from tello-sdk/tello.py rename to tello_sdk/tello.py index 9a8b1a1..bdb768d 100644 --- a/tello-sdk/tello.py +++ b/tello_sdk/tello.py @@ -76,7 +76,7 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): logging.info(' Drone Script ') logging.info('--------------------------------------') - logging.debug('Current port for UDP connection: %s', str(port)) + logging.debug(f'Current port for UDP connection: {str(port)}') logging.info(' Checking network... \r\n') time.sleep(0.5) @@ -152,7 +152,7 @@ def run(self, command: str, message: str = "No tips available for this command " # Send the encoded message to the Tello self.sent = self.sock.sendto(command, self.tello_address) if self.tips: - logging.info(message) + print('--:--:-- [TIP] ' + message) self.response = None timer.start() while self.response is None: @@ -182,7 +182,7 @@ def throw_fly(self): 'Gently toss the drone into the air within 5 seconds!\r\n' ) - def motor_on(self): + def motors_on(self): """Sends command to turn on motors""" logging.debug('Sending command: motor_on()') return self.run( @@ -190,7 +190,7 @@ def motor_on(self): 'Turning on motors\r\n' ) - def motor_off(self): + def motors_off(self): """Sends command to turn off motors""" logging.debug('Sending command: motor_off()') return self.run( @@ -309,9 +309,9 @@ def set_rmtt_wifi(self, ssid: str, password: str): ) # SDK 2.0 Commands - def connect(self): + def init(self): """Sends command to initialize SDK mode""" - logging.debug('Sending command: connect()') + logging.debug('Sending command: init()') return self.run( 'command', 'Enabling SDK mode\r\n' @@ -360,9 +360,9 @@ def emergency(self, reason='No reason provided'): logging.debug('Emergency stop due to: %s. Unable to continue due to motor stop. Exiting.', reason) sys.exit() - def stop_movement(self): - """Sends command to stop all movement""" - logging.debug('Sending command: stop_movement()') + def hover(self): + """Sends command to stop all movement, hover""" + logging.debug('Sending command: hover()') return self.run( 'stop', 'Stopping all movement, hovering.\r\n' @@ -434,35 +434,33 @@ def back(self, x: int): logging.warning('tello.back(): Invalid value.') return 'error' - def cw(self, x: int): - """Sends command to rotate clockwise x degrees""" + def rotate(self, direction: str, degrees: int): + """Sends command to rotate clockwise or anti-clockwise for specified amount of degrees""" logging.debug('Sending command: cw()') - if 1 <= x <= 360: - return self.run( - f'cw {str(x)}', - f'Rotating clockwise for {str(x)} degrees \r\n' - ) - logging.warning('tello.cw(): Invalid value.') + if 1 <= degrees <= 360: + if direction is 'cw': + return self.run( + f'cw {str(degrees)}', + f'Rotating clockwise {str(degrees)} degrees \r\n' + ) + if direction is 'ccw': + return self.run( + f'ccw {str(degrees)}', + f'Rotating counter-clockwise {str(degrees)} degrees \r\n' + ) + logging.warning('tello.rotate(): Invalid direction.') + return 'error' + logging.warning('tello.rotate(): Invalid value.') return 'error' - def ccw(self, x: int): - """Sends command to rotate counter-clockwise x degrees""" - logging.debug('Sending command: ccw()') - if 1 <= x <= 360: - return self.run( - f'ccw {str(x)}', - f'Rotating counter-clockwise for {str(x)} degrees \r\n' - ) - logging.warning('tello.ccw(): Invalid value.') - return 'error' - def flip(self, x: str): - """Sends command to flip in direction x""" + def flip(self, direction: str): + """Sends command to flip in direction specified""" logging.debug('Sending command: flip()') - if x in ('l', 'r', 'f', 'b'): + if direction in ('l', 'r', 'f', 'b'): return self.run( - f'flip {x}', - f'Flipping {x}, be careful \r\n' + f'flip {direction}', + f'Flipping {direction}, be careful \r\n' ) logging.warning('tello.flip(): Invalid value.') return 'error' diff --git a/tello-sdk/telloLive.py b/tello_sdk/telloLive.py similarity index 100% rename from tello-sdk/telloLive.py rename to tello_sdk/telloLive.py From 7ea128ae779f1699378a2d69d2f0ba26aab3252e Mon Sep 17 00:00:00 2001 From: ErnGusMik <77016061+ErnGusMik@users.noreply.github.com> Date: Sun, 18 Sep 2022 19:48:31 +0300 Subject: [PATCH 09/18] v2.2.1-alpha --- README.md | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7507f35..e06114a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.1.0 Alpha*
+*2.2.0 Alpha*
SDK 3.0 is **here** and **tested**! Documentation in progress! ## Requirements: * Python installed on your system or as a VS Code extension @@ -9,20 +9,12 @@ SDK 3.0 is **here** and **tested**! Documentation in progress! * This package ## Quickstart -This quickstart focuses on the file edition. -To get instructions for the live edition, go to [Tello Live Edition Guide]() -```python -import telloFile # Imports library -tello = telloFile.Tello() # Sets var tello as the class -tello.connect() # Initializes SDK mode (more below) -``` -*(WRITEHERE.py)* -## Usage -The library consists of callable functions. -To see `set` functions, please go [here](SET%26READ_GUIDE.md) -To see `complex` functions, please go [here](COMPLEX_GUIDE.md) -To see examples, please go [here]() +Please see the [Wiki](https://github.com/ErnGusMik/python-tello/wiki) + + +--- +--- ### tello.connect() Initializes SDK mode. From 9d5697d4d6714bad9365f046fe098f0929e1df93 Mon Sep 17 00:00:00 2001 From: ErnGusMik Date: Sat, 24 Sep 2022 19:01:34 +0300 Subject: [PATCH 10/18] v2.3.0 --- README.md | 7 +++++- tello_sdk/tello.py | 62 ++++++++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index e06114a..2a827eb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Python Tello This is a library for easy usage of the Ryze Tello drone education edition.
**Current Version:** -*2.2.0 Alpha*
+*2.3.0 Alpha*
SDK 3.0 is **here** and **tested**! Documentation in progress! ## Requirements: * Python installed on your system or as a VS Code extension @@ -208,6 +208,11 @@ tello.end() ``` ## Version history: +**2.3.0-alpha** +* Naming changes +* Added tello_version() +* Did research. + **2.1.0-alpha** * Tested all new EXT commands * Tested most other new commands diff --git a/tello_sdk/tello.py b/tello_sdk/tello.py index bdb768d..5a97029 100644 --- a/tello_sdk/tello.py +++ b/tello_sdk/tello.py @@ -57,7 +57,7 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): self.response = None self.sent = None self.ip = None - self.info_port = 8889 + self.status_port = 8889 self.video_port = 11111 # Set variables for connection to drone @@ -212,19 +212,19 @@ def reboot(self): return 'ok' # SDK 3.0 SET Commands - def rc(self, roll: int = 0, pitch: int = 0, yaw: int = 0, throttle: int = 0): + def rc(self, roll: int = 0, pitch: int = 0, throttle: int = 0, yaw: int = 0): """Sends command to adjust lever force values (acc. to official docs)""" logging.debug('Sending command: rc()') if 100 >= roll >= -100 and 100 >= pitch >= -100 and 100 >= yaw >= -100 and 100 >= throttle >= -100: self.run( - f'rc {roll} {pitch} {yaw} {throttle}', + f'rc {roll} {pitch} {throttle} {yaw}', 'Setting lever force values\r\n' ) return 'ok' logging.warning('tello.rc(): Invalid value.') return 'error' - def ap(self, ssid: str, password: str): + def set_ap(self, ssid: str, password: str): """Sends command to join access point, then reboot""" logging.debug('Sending command: ap()') return self.run( @@ -236,30 +236,30 @@ def set_wifi_channel(self, channel: int): """Sends command to set the WiFi channel""" logging.debug('Sending command: set_wifi_channel()') return self.run( - f'wifi {channel}', + f'wifisetchannel {channel}', f'Setting Wi-Fi channel to {channel} channel\r\n' ) - def set_port(self, info_port: int, video_port: int): + def set_ports(self, status_port: int, video_port: int): """Sends command to set the ports for status and video""" - logging.debug('Sending command: set_port()') - if 1025 <= info_port <= 65535 and 1025 <= video_port <= 65535: + logging.debug('Sending command: set_ports()') + if 1025 <= status_port <= 65535 and 1025 <= video_port <= 65535: ports = self.run( - f'port {info_port} {video_port}', + f'port {status_port} {video_port}', 'Setting new ports for status and video\r\n' ) if ports == 'ok': - logging.info('New ports set by client: %s and %s', info_port, video_port) - self.info_port = info_port - self.tello_address = ('192.168.10.1', info_port) + logging.info('New ports set by client: %s and %s', status_port, video_port) + # self.info_port = status_port + # self.tello_address = ('192.168.10.1', info_port) # # SET VIDEO PORT # return 'ok' - logging.warning('tello.set_port(): Failed to set ports.') + logging.warning('tello.set_ports(): Failed to set ports.') logging.debug('Failed to set ports due to an error response from the drone.') return 'error' - logging.warning('tello.set_port(): Invalid value.') + logging.warning('tello.set_ports(): Invalid value.') return 'error' def set_fps(self, fps: str): @@ -465,6 +465,7 @@ def flip(self, direction: str): logging.warning('tello.flip(): Invalid value.') return 'error' + # SET Commands def set_speed(self, x: int): """Sends command to set speed to x cm/s""" logging.debug('Sending command: set_speed()') @@ -529,7 +530,7 @@ def get_battery(self): 'Obtaining battery level \r\n' ) - def get_time(self): + def get_flight_time(self): """Sends command to get flight time""" logging.debug('Sending command: get_time()') return self.run( @@ -537,9 +538,9 @@ def get_time(self): 'Obtaining current flight time \r\n' ) - def get_wifi(self): - """Sends command to get wifi info""" - logging.debug('Sending command: get_wifi()') + def get_wifi_snr(self): + """Sends command to get wifi SNR""" + logging.debug('Sending command: get_wifi_snr()') return self.run( 'wifi?', 'Obtaining WiFi SNR \r\n' @@ -552,6 +553,13 @@ def get_sdk(self): 'sdk?', 'Obtaining Tello SDK Version \r\n' ) + def get_version(self): + """Sends command to get Tello version""" + logging.debug('Sending command: get_version()') + return self.run( + 'version?', + 'Obtaining Tello Version \r\n' + ) def get_sn(self): """Sends command to get serial number""" @@ -574,7 +582,7 @@ def get_rmtt_wifi_version(self): """Sends command to get RMTT WiFi version""" logging.debug('Sending command: get_rmtt_wifi_version()') return self.run( - 'wifi?', + 'wifiversion?', 'Obtaining RMTT WiFi version \r\n' ) @@ -586,7 +594,7 @@ def get_ap(self): 'Obtaining RMTT Access Point SSID and password \r\n' ) - def get_ssid(self): + def get_rmtt_wifi(self): """Sends command to get RMTT SSID""" logging.debug('Sending command: get_ssid()') return self.run( @@ -804,17 +812,17 @@ def set_display_brightness(self, brightness: int): logging.warning('tello.set_display_brightness(): Invalid brightness.') return 'matrix error' - def get_height(self): - """Sends command to get the distance of the drone from the floor""" - logging.debug('Sending command: get_height()') + def get_tof(self): + """Sends command to get the distance from the drone to the nearest obstacle in front""" + logging.debug('Sending command: get_tof()') return self.run( 'EXT tof?', - 'Getting height...\r\n' + 'Getting ToF (read docs for more info)...\r\n' ) - def get_rmtt_version(self): - """Sends command to get the RMTT version""" - logging.debug('Sending command: get_rmtt_version()') + def get_esp32_version(self): + """Sends command to get the ESP32 version""" + logging.debug('Sending command: get_esp32_version()') return self.run( 'EXT version?', 'Getting RMTT version...\r\n' From f2425009eb21b2e3afbf8c111d89fbcaec105685 Mon Sep 17 00:00:00 2001 From: ErnGusMik Date: Wed, 9 Nov 2022 12:55:48 +0200 Subject: [PATCH 11/18] v2.4.1 Stable --- README.md | 282 ++++------------------------------------------------ VERSIONS.md | 69 +++++++++++++ setup.py | 13 +-- 3 files changed, 96 insertions(+), 268 deletions(-) create mode 100644 VERSIONS.md diff --git a/README.md b/README.md index 2a827eb..04844cc 100644 --- a/README.md +++ b/README.md @@ -1,272 +1,34 @@ # Python Tello -This is a library for easy usage of the Ryze Tello drone education edition.
+This is a library for easy usage of the Ryze Tello drone education edition and RoboMaster Tello Talent. Beginner Friendly!
**Current Version:** -*2.3.0 Alpha*
-SDK 3.0 is **here** and **tested**! Documentation in progress! +*2.4.1*
+SDK 3.0 is **here** and **tested**! ## Requirements: -* Python installed on your system or as a VS Code extension -* Ryze Tello EDU Edition (get one [here](https://www.ryzerobotics.com/tello-edu)) +* Python 3.6 or higher installed on your system (get it on [python.org](https://www.python.org/)) +* Ryze Tello EDU Edition (get one [here](https://www.ryzerobotics.com/tello-edu)) OR RoboMaster Tello Talent (get one [here](https://store.dji.com/product/robomaster-tt)) * This package -## Quickstart -Please see the [Wiki](https://github.com/ErnGusMik/python-tello/wiki) +## Documentation +To see the documentation, please go to the GitHub Wiki of this project, available [here](https://github.com/ErnGusMik/python-tello/wiki) - ---- ---- - -### tello.connect() -Initializes SDK mode. -Must be run as the first function every time the script runs.
-Possible responses: `ok` / `error`
-Example: -```python -tello.connect() -``` -### tello.takeoff() -Automatic takeoff.
-Possible responses: `ok` / `error`
-Example: -```python -tello.takeoff() -``` - -### tello.land() -Automatic landing.
-Possible responses: `ok` / `error`
-Example: -```python -tello.land() -``` - -### tello.video_stream_on() -Enable video stream.
-**Camera functionality under development**
-Possible responses: `ok` / `error`
-Example: -```python -tello.streamon() -``` - -### tello.video_stream_off() -Disable video stream.
-**Camera functionality under development**
-Possible responses: `ok` / `error`
-Example: -```python -tello.streamoff() -``` - -### tello.emergency() -Stops all motors immediately.
-**Danger of drone falling!**
-Possible responses: `ok` / `error`
-Parameters: -* reason: String, *optional*. Reason for stopping motors.
-Example: -```python -tello.emergency('The drone has hit a wall') -``` - -### tello.stop() -Stops all movement and hovers in the air.
-Possible responses: `ok` / `error`
-Example: -```python -tello.stop() +## Getting Started +You can get this package on PyPi (pip) and GitHub. +To donwload using GitHub, please click [this link](https://github.com/ErnGusMik/python-tello/archive/refs/heads/main.zip). The package will start downloading. +To download using pip, enter the following in your terminal interface (Command Prompt on Windows): +```bash +user@os$ pip install tello-sdk ``` +[More info in the Docs](https://github.com/ErnGusMik/python-tello/wiki) -### tello.up(x) -Ascends to *x* cm off the ground.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Height in cm. Allowed values: 20-500
-Example: -```python -tello.up(30) -``` - -### tello.down(x) -Descends to *x* cm off the ground.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Height in cm. Allowed values: 20-500
-Example: -```python -tello.down(100) -``` - -### tello.left(x) -Goes left for *x* cm.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Distance in cm. Allowed values: 20-500
-Example: -```python -tello.left(249) -``` - -### tello.right(x) -Goes right for *x* cm.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Distance in cm. Allowed values: 20-500
-Example: -```python -tello.right(23) -``` - -### tello.forward(x) -Goes forwards for *x* cm.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Distance in cm. Allowed values: 20-500
-Example: -```python -tello.forward(500) -``` - -### tello.back(x) -Goes backwards for *x* cm.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Distance in cm. Allowed values: 20-500
-Example: -```python -tello.back(65) -``` - -### tello.cw(x) -Rotates clockwise for *x* degrees.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Degrees to turn. Allowed values: 1-360
-Example: -```python -tello.cw(100) -``` - -### tello.ccw(x) -Rotates counter-clockwise for *x* degrees.
-Possible responses: `ok` / `error`
-Parameters: -* x: Integer. Degrees to turn. Allowed values: 1-360
-Example: -```python -tello.ccw(359) -``` - -### tello.flip(x) -Flips drone in *x* direction.
-Possible responses: `ok` / `error`
-Parameters: -* x: String. Direction to flip. Allowed values: `'f'` (forwards), `'b'` (backwards), `'l'` (left), `'r'` (right)
-Example: -```python -tello.flip('l') -``` - -### tello.throw_fly() -Toss the drone in the air within 5 seconds of receiving response to takeoff
-Possible responses: `ok` / `error`
-Example: -```python -tello.throw_fly() -``` - -### tello.motor_on() -Turns on motors (at a slow RPM)
-Possible responses: `ok` / `error`
-Example: -```python -tello.motor_on() -``` - -### tello.motor_off() -Turns off motors (use motor_on() first)
-Possible responses: `ok` / `error`
-Example: -```python -tello.motor_off() -``` - -### tello.throw_fly() -Turns off motors (use tello.motoron() first)
-Possible responses: `ok` / `error`
-Example: -```python -tello.motoroff() -``` - -### tello.end() -Ends the program.
-Possible responses: `ok` / Thrown `error`
-Example: -```python -tello.end() -``` - -## Version history: -**2.3.0-alpha** -* Naming changes -* Added tello_version() -* Did research. - -**2.1.0-alpha** -* Tested all new EXT commands -* Tested most other new commands -* setup.py changes (long-description) -* deepsource.toml changes (max-line-limt: 100) -* tello.set_display_ascii_character() is still being tested. - -**2.0.5-alpha** -* setup.py changes -* Re-releasing on pip - -**2.0.4-alpha** -* Readded .deepsource.toml -* Hopefully fixed pip 'No Description provided' issue - -**2.0.3-alpha** -* Reorganized structure for PyPi -* Added LICENSE.txt (MIT License) -* Added setup.cfg -* Added setup.py and configured for PyPi -* Added tello-sdk/__init__.py -* We're pip installable now! - -**2.0.2-alpha** -* Style fixes -* Started work on going pip-ready :) -* Changed all print to logging (for easier debugging) -* Added debugging and tips options to Tello class - -**2.0.1-alpha** -* Small fixes - -**2.0-alpha** -* All new Tello SDK 3.0 commands implemented! -* Small potential bug/style fixes -* This is an Alpha version, so it is **not** stable, by any means! - - -**1.1.2-alpha** -* Potential bug fixes -* Security issue fix -* Performance optimizations -* Remodel of __init__ function - +## Usage +The library is beginner friendly. Even if you are new to programming, usage should be easy. +The Tello SDK library is made of callable functions that make the drone do something. -**1.1-beta:** -* Implementation of some Tello SDK 3.0 commands -* Naming changes -* Functions now return the response -* In development: camera functions, customization, SDK 3.0 full implementation -* V1.1.1: spelling fix +[For function names, refer to the Docs](https://github.com/ErnGusMik/python-tello/wiki) +## Contributors +This library was created entirely by ErnGusMik -**1.0-beta:** -* Implement most of Tello SDK 2.0 commands -* Documentation started -* `tello.run()` command for executing any command straight to the drone. +## Licence +This library is licenced under the MIT licence. diff --git a/VERSIONS.md b/VERSIONS.md new file mode 100644 index 0000000..5d8adde --- /dev/null +++ b/VERSIONS.md @@ -0,0 +1,69 @@ +# Tello & RMTT SDK +## Version history: +**2.4.1** +* Documentation finished +* Redone README.md +* Added VERSIONS.md + +**2.3.0-alpha** +* Naming changes +* Added tello_version() +* Did research. + +**2.1.0-alpha** +* Tested all new EXT commands +* Tested most other new commands +* setup.py changes (long-description) +* deepsource.toml changes (max-line-limt: 100) +* tello.set_display_ascii_character() is still being tested. + +**2.0.5-alpha** +* setup.py changes +* Re-releasing on pip + +**2.0.4-alpha** +* Readded .deepsource.toml +* Hopefully fixed pip 'No Description provided' issue + +**2.0.3-alpha** +* Reorganized structure for PyPi +* Added LICENSE.txt (MIT License) +* Added setup.cfg +* Added setup.py and configured for PyPi +* Added tello-sdk/__init__.py +* We're pip installable now! + +**2.0.2-alpha** +* Style fixes +* Started work on going pip-ready :) +* Changed all print to logging (for easier debugging) +* Added debugging and tips options to Tello class + +**2.0.1-alpha** +* Small fixes + +**2.0-alpha** +* All new Tello SDK 3.0 commands implemented! +* Small potential bug/style fixes +* This is an Alpha version, so it is **not** stable, by any means! + + +**1.1.2-alpha** +* Potential bug fixes +* Security issue fix +* Performance optimizations +* Remodel of __init__ function + + +**1.1-beta:** +* Implementation of some Tello SDK 3.0 commands +* Naming changes +* Functions now return the response +* In development: camera functions, customization, SDK 3.0 full implementation +* V1.1.1: spelling fix + + +**1.0-beta:** +* Implement most of Tello SDK 2.0 commands +* Documentation started +* `tello.run()` command for executing any command straight to the drone. \ No newline at end of file diff --git a/setup.py b/setup.py index 83c6902..6e5465d 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ from setuptools import setup, find_packages - def readme(): with open('README.md') as f: return f.read() @@ -7,21 +6,19 @@ def readme(): setup( name='tello-sdk', packages=find_packages('tello_sdk'), - version='2.1.0', + version='2.4.1', license='MIT', - description='Python SDK fro the Tello EDU and RMTT drones, with all commands and more', + description='Python SDK fro the Tello EDU and RMTT drones, with all commands and more.', author='ErnGusMik', author_email='ernests.mikuts@gmail.com', url='https://github.com/ErnGusMik/python-tello', download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.1.0-alpha.tar.gz', keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], - install_requires=[ - 'sentry-sdk' - ], + install_requires=[ 'sentry-sdk' ], long_description=readme(), long_description_content_type='text/markdown', classifiers=[ - 'Development Status :: 3 - Alpha', + 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Topic :: Software Development :: Build Tools', 'License :: OSI Approved :: MIT License', @@ -32,4 +29,4 @@ def readme(): 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', ] -) +) \ No newline at end of file From 1a2b5006ca23291bc9a586da85e82e7a7be613c5 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 9 Nov 2022 10:56:42 +0000 Subject: [PATCH 12/18] Restyled by autopep8 --- setup.py | 10 ++++--- tello_sdk/tello.py | 59 +++++++++++++++++++++++++++--------------- tello_sdk/telloLive.py | 20 +++++++++----- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/setup.py b/setup.py index 6e5465d..d83e9fa 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,11 @@ from setuptools import setup, find_packages + + def readme(): with open('README.md') as f: return f.read() + setup( name='tello-sdk', packages=find_packages('tello_sdk'), @@ -13,8 +16,9 @@ def readme(): author_email='ernests.mikuts@gmail.com', url='https://github.com/ErnGusMik/python-tello', download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.1.0-alpha.tar.gz', - keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], - install_requires=[ 'sentry-sdk' ], + keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', + 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], + install_requires=['sentry-sdk'], long_description=readme(), long_description_content_type='text/markdown', classifiers=[ @@ -29,4 +33,4 @@ def readme(): 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', ] -) \ No newline at end of file +) diff --git a/tello_sdk/tello.py b/tello_sdk/tello.py index 5a97029..4d0c8e6 100644 --- a/tello_sdk/tello.py +++ b/tello_sdk/tello.py @@ -83,7 +83,8 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): # Check what network is connected if sys.platform == 'win32': - wifi = subprocess.check_output(['/windows/system32/netsh', 'WLAN', 'show', 'interfaces']) + wifi = subprocess.check_output( + ['/windows/system32/netsh', 'WLAN', 'show', 'interfaces']) data = wifi.decode('utf-8') wifi_val = 'Not connected' for line in data.split('\n'): @@ -95,12 +96,13 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): logging.debug('Required network detected.') else: logging.debug('Network detected') - logging.warning('It seems like you have not joined the TELLO- or RMTT-network. Please make sure that you have joined the TELLO- or RMTT- Wi-Fi.') + logging.warning( + 'It seems like you have not joined the TELLO- or RMTT-network. Please make sure that you have joined the TELLO- or RMTT- Wi-Fi.') elif sys.platform == 'darwin': process = subprocess.Popen([ '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I' - ], stdout=subprocess.PIPE) + ], stdout=subprocess.PIPE) out, _ = process.communicate() process.wait() wifi_val = 'Not connected' @@ -111,12 +113,14 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): wifi_val = val if 'TELLO-' not in wifi_val or 'RMTT-' not in wifi_val: logging.debug('Network detected: %s', wifi_val) - logging.warning('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') + logging.warning( + 'It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') else: logging.debug('Required network detected: %s', wifi_val) else: logging.warning('Could not determine network.') - logging.warning('Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks.') + logging.warning( + 'Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks.') # Print info to the user logging.info(' Making UDP socket... \r\n') @@ -249,7 +253,8 @@ def set_ports(self, status_port: int, video_port: int): 'Setting new ports for status and video\r\n' ) if ports == 'ok': - logging.info('New ports set by client: %s and %s', status_port, video_port) + logging.info('New ports set by client: %s and %s', + status_port, video_port) # self.info_port = status_port # self.tello_address = ('192.168.10.1', info_port) # @@ -257,7 +262,8 @@ def set_ports(self, status_port: int, video_port: int): # return 'ok' logging.warning('tello.set_ports(): Failed to set ports.') - logging.debug('Failed to set ports due to an error response from the drone.') + logging.debug( + 'Failed to set ports due to an error response from the drone.') return 'error' logging.warning('tello.set_ports(): Invalid value.') return 'error' @@ -357,7 +363,8 @@ def emergency(self, reason='No reason provided'): 'Emergency stop. Attempting to stop motors.\r\n' ) logging.critical('Emergency stop. Exiting script.') - logging.debug('Emergency stop due to: %s. Unable to continue due to motor stop. Exiting.', reason) + logging.debug( + 'Emergency stop due to: %s. Unable to continue due to motor stop. Exiting.', reason) sys.exit() def hover(self): @@ -453,7 +460,6 @@ def rotate(self, direction: str, degrees: int): logging.warning('tello.rotate(): Invalid value.') return 'error' - def flip(self, direction: str): """Sends command to flip in direction specified""" logging.debug('Sending command: flip()') @@ -481,7 +487,8 @@ def set_wifi(self, ssid: str, passw: str): """Sends command to set wifi ssid and passw""" logging.debug('Sending command: set_wifi()') logging.info('SSID: %s, PASSWORD: %s', ssid, passw) - logging.debug('Please note that you will not be able to connect to the drone if you forget this password!') + logging.debug( + 'Please note that you will not be able to connect to the drone if you forget this password!') return self.run( f'wifi {ssid}, {passw}', f'Setting wifi to {ssid}, with password {passw} then rebooting\r\n' @@ -553,6 +560,7 @@ def get_sdk(self): 'sdk?', 'Obtaining Tello SDK Version \r\n' ) + def get_version(self): """Sends command to get Tello version""" logging.debug('Sending command: get_version()') @@ -624,7 +632,8 @@ def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): if 60 >= s >= 10: return self.run( f'curve {str(x1)} {str(y1)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)}', - f'Curving from (x, y, z): {str(x1)} {str(y1)} {str(z1)} to {str(x2)} {str(y2)} {str(z2)} at the speed of', str(s), 'cm/s\r\n' + f'Curving from (x, y, z): {str(x1)} {str(y1)} {str(z1)} to {str(x2)} {str(y2)} {str(z2)} at the speed of', str( + s), 'cm/s\r\n' ) logging.warning('tello.curve(): Invalid speed.') return 'error' @@ -646,7 +655,8 @@ def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): f'go {str(x)} {str(y)} {str(z)} {str(s)} {str(mid)}', f'Going to (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n' ) - logging.warning('tello.go_mission_pad(): Invalid mission pad ID.') + logging.warning( + 'tello.go_mission_pad(): Invalid mission pad ID.') return 'error' logging.warning('tello.go_mission_pad(): Invalid speed.') return 'error' @@ -668,7 +678,8 @@ def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int f'curve {str(x1)} {str(x2)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)} {str(mid)}', f'Curving from (x, y, z): {x1} {y1} {z1} to {x2} {y2} {z2} at the speed of {str(s)} cm/s\r\n' ) - logging.warning('tello.curve_mission_pad(): Invalid mission pad ID.') + logging.warning( + 'tello.curve_mission_pad(): Invalid mission pad ID.') return 'error' logging.warning('tello.curve_mission_pad(): Invalid speed.') return 'error' @@ -683,7 +694,7 @@ def set_light_off(self): # TO TEST 'EXT led 0 0 0', 'Turning off the big light\r\n' ) - + def set_light_color(self, r: int, g: int, b: int): """Sends command to set the color of the LED""" logging.debug('Sending command: set_light_color()') @@ -722,13 +733,14 @@ def set_display_pattern(self, pattern: str = '0'): logging.debug('Sending command: set_display_pattern()') for char in pattern: if char not in 'rbp0': - logging.warning('tello.set_display_pattern(): Invalid pattern.') + logging.warning( + 'tello.set_display_pattern(): Invalid pattern.') return 'matrix error' return self.run( f'EXT mled g {str(pattern)}', f'Setting RMTT display pattern to: {str(pattern)} \r\n' ) - + def set_display_blank(self): # TO TEST """Sends command to make the display blank""" logging.debug('Sending command: set_display_off()') @@ -736,12 +748,14 @@ def set_display_blank(self): # TO TEST 'EXT mled g 0000000000000000000000000000000000000000000000000000000000000000', 'Turning off the display\r\n' ) + def set_display_string(self, direction: str, color: str, frame_rate: float or int, string: str): """Sends command to show a string on the display""" logging.debug('Sending command: set_display_string()') for char in direction: if char not in 'lrud': - logging.warning('tello.set_display_string(): Invalid direction.') + logging.warning( + 'tello.set_display_string(): Invalid direction.') return 'matrix error' if color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1: return self.run( @@ -756,11 +770,13 @@ def set_display_moving_image(self, direction: str, color: str, frame_rate: float logging.debug('Sending command: set_display_moving_image()') for char in direction: if char not in 'lrud': - logging.warning('tello.set_display_moving_image(): Invalid direction.') + logging.warning( + 'tello.set_display_moving_image(): Invalid direction.') return 'matrix error' for char in pattern: if char not in 'rbp0': - logging.warning('tello.set_display_moving_image(): Invalid pattern.') + logging.warning( + 'tello.set_display_moving_image(): Invalid pattern.') return 'matrix error' if color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1: return self.run( @@ -770,12 +786,13 @@ def set_display_moving_image(self, direction: str, color: str, frame_rate: float logging.warning('tello.set_display_moving_image(): Invalid values.') return 'matrix error' - def set_display_ascii_character(self, character: str, color: str): # TEST + def set_display_ascii_character(self, character: str, color: str): # TEST """Sends command to display ascii character""" logging.debug('Sending command: set_display_ascii_character()') if character == 'heart' or character.encode('ascii') and color in ('r', 'b', 'p'): return self.run( - f'EXT mled s {str(color)} {str(character.encode("ascii"))}', # TEST + # TEST + f'EXT mled s {str(color)} {str(character.encode("ascii"))}', f'Displaying ASCII character: {str(character)} with color: {str(color)} \r\n' ) logging.warning('tello.set_display_ascii_character(): Invalid values.') diff --git a/tello_sdk/telloLive.py b/tello_sdk/telloLive.py index 67c5339..6755d93 100644 --- a/tello_sdk/telloLive.py +++ b/tello_sdk/telloLive.py @@ -32,7 +32,7 @@ process = subprocess.Popen([ '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I' - ], stdout=subprocess.PIPE) + ], stdout=subprocess.PIPE) out, err = process.communicate() process.wait() wifi_val = {} @@ -44,7 +44,8 @@ if 'TELLO-' not in wifi_val: print('Network detected:', wifi_val) print('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') - approval = input("Are you sure you want to continue with the script? (y/n)") + approval = input( + "Are you sure you want to continue with the script? (y/n)") if approval == 'y': print('\r\n') else: @@ -88,10 +89,13 @@ def recv(): break -print("\r\nTo view all available functions, type", '\033[1m' + 'help' + '\033[0m') +print("\r\nTo view all available functions, type", + '\033[1m' + 'help' + '\033[0m') print("\r\nTo quit the script, type", '\033[1m' + 'end' + '\033[0m') -print("\r\n(For emergencies) To immediately quit the script, press", '\033[1m' + 'Ctrl + C' + '\033[0m') -print("\r\nIMPORTANT! Do", '\033[1m' + 'not' + '\033[0m', 'type until a response is received!') +print("\r\n(For emergencies) To immediately quit the script, press", + '\033[1m' + 'Ctrl + C' + '\033[0m') +print("\r\nIMPORTANT! Do", '\033[1m' + 'not' + + '\033[0m', 'type until a response is received!') print("\r\nTo begin, type", '\033[1m' + 'command' + '\033[0m: \r\n') @@ -127,9 +131,11 @@ def recv(): print(' streamoff -- Disable video stream') print(' emergency -- Stop motors immediately') print(' up/down x -- Ascend/descend to x cm (20-500)') - print(' left/right/forward/back x -- Fly forward/backward/left/right for x cm (20-500)') + print( + ' left/right/forward/back x -- Fly forward/backward/left/right for x cm (20-500)') print(' cw/ccw x -- Rotate clockwise/counterclockwise x degrees (1-360)') - print(' flip x -- Flip in the x direction (l (left), r (right), f (forw.), b (backw.))') + print( + ' flip x -- Flip in the x direction (l (left), r (right), f (forw.), b (backw.))') print(' stop -- Hover in the air') print('\r\nTo view set, read and hard functions, type \'help set\', \'help read\' or \'help hard\' \r\n\r\n') elif msg == 'help hard': From ac8f2784fa8e1cf9c2e68bcf0d6eecb0e286e52c Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 9 Nov 2022 10:56:45 +0000 Subject: [PATCH 13/18] Restyled by black --- setup.py | 61 +-- tello_sdk/tello.py | 822 +++++++++++++++++++---------------------- tello_sdk/telloLive.py | 246 ++++++------ 3 files changed, 559 insertions(+), 570 deletions(-) diff --git a/setup.py b/setup.py index d83e9fa..7121111 100644 --- a/setup.py +++ b/setup.py @@ -2,35 +2,46 @@ def readme(): - with open('README.md') as f: + with open("README.md") as f: return f.read() setup( - name='tello-sdk', - packages=find_packages('tello_sdk'), - version='2.4.1', - license='MIT', - description='Python SDK fro the Tello EDU and RMTT drones, with all commands and more.', - author='ErnGusMik', - author_email='ernests.mikuts@gmail.com', - url='https://github.com/ErnGusMik/python-tello', - download_url='https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.1.0-alpha.tar.gz', - keywords=['tello', 'drone', 'sdk', 'python', 'python3', 'rmtt', - 'edu', 'telloedu', 'tello-rmtt', 'tello-edu', 'sdk'], - install_requires=['sentry-sdk'], + name="tello-sdk", + packages=find_packages("tello_sdk"), + version="2.4.1", + license="MIT", + description="Python SDK fro the Tello EDU and RMTT drones, with all commands and more.", + author="ErnGusMik", + author_email="ernests.mikuts@gmail.com", + url="https://github.com/ErnGusMik/python-tello", + download_url="https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.1.0-alpha.tar.gz", + keywords=[ + "tello", + "drone", + "sdk", + "python", + "python3", + "rmtt", + "edu", + "telloedu", + "tello-rmtt", + "tello-edu", + "sdk", + ], + install_requires=["sentry-sdk"], long_description=readme(), - long_description_content_type='text/markdown', + long_description_content_type="text/markdown", classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Build Tools', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - ] + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: Software Development :: Build Tools", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + ], ) diff --git a/tello_sdk/tello.py b/tello_sdk/tello.py index 4d0c8e6..6ccb783 100644 --- a/tello_sdk/tello.py +++ b/tello_sdk/tello.py @@ -17,13 +17,13 @@ # ------------------ # sentry_sdk.init( dsn="https://f2fcaa10be4f41958ab756183583ba81@o1400261.ingest.sentry.io/6728983", - traces_sample_rate=1.0 + traces_sample_rate=1.0, ) # ------------------ # # Class for all functions for user -class Tello(): +class Tello: """Class for info commands to the Tello or RMTT drones""" def __init__(self, log_in_console: bool = True, tips: bool = True): @@ -31,21 +31,21 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): # Configure logging if log_in_console: logging.basicConfig( - format='%(asctime)s [%(levelname)s] %(message)s ', - datefmt='%H:%M:%S', + format="%(asctime)s [%(levelname)s] %(message)s ", + datefmt="%H:%M:%S", level=logging.INFO, handlers=[ logging.StreamHandler(sys.stdout), - logging.FileHandler('debug.log', mode='w') - ] + logging.FileHandler("debug.log", mode="w"), + ], ) else: logging.basicConfig( - format='%(asctime)s [%(levelname)s] %(message)s ', - datefmt='%H:%M:%S', + format="%(asctime)s [%(levelname)s] %(message)s ", + datefmt="%H:%M:%S", level=logging.DEBUG, - filename='debug.log', - filemode='w' + filename="debug.log", + filemode="w", ) # Set self variables @@ -61,82 +61,89 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): self.video_port = 11111 # Set variables for connection to drone - host = '' + host = "" port = 9000 locaddr = (host, port) - self.mids = 'm1 m2 m3 m4 m5 m6 m7 m8' + self.mids = "m1 m2 m3 m4 m5 m6 m7 m8" # Print starting info for the user - logging.info('--------------------------------------') - logging.info('_________ ____ ____ ') - logging.info(' | | | | | |') - logging.info(' | |___ | | | |') - logging.info(' | | | | | |') - logging.info(' | |____ |____ |____ |____|\r\n') - logging.info(' Drone Script ') - logging.info('--------------------------------------') - - logging.debug(f'Current port for UDP connection: {str(port)}') - - logging.info(' Checking network... \r\n') + logging.info("--------------------------------------") + logging.info("_________ ____ ____ ") + logging.info(" | | | | | |") + logging.info(" | |___ | | | |") + logging.info(" | | | | | |") + logging.info(" | |____ |____ |____ |____|\r\n") + logging.info(" Drone Script ") + logging.info("--------------------------------------") + + logging.debug(f"Current port for UDP connection: {str(port)}") + + logging.info(" Checking network... \r\n") time.sleep(0.5) # Check what network is connected - if sys.platform == 'win32': + if sys.platform == "win32": wifi = subprocess.check_output( - ['/windows/system32/netsh', 'WLAN', 'show', 'interfaces']) - data = wifi.decode('utf-8') - wifi_val = 'Not connected' - for line in data.split('\n'): + ["/windows/system32/netsh", "WLAN", "show", "interfaces"] + ) + data = wifi.decode("utf-8") + wifi_val = "Not connected" + for line in data.split("\n"): if "SSID: " in line: - _, val = line.split(': ') + _, val = line.split(": ") val = val.strip() wifi_val = val if "TELLO-" in data or "RMTT-" in data: - logging.debug('Required network detected.') + logging.debug("Required network detected.") else: - logging.debug('Network detected') + logging.debug("Network detected") logging.warning( - 'It seems like you have not joined the TELLO- or RMTT-network. Please make sure that you have joined the TELLO- or RMTT- Wi-Fi.') - elif sys.platform == 'darwin': - process = subprocess.Popen([ - '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', - '-I' - ], stdout=subprocess.PIPE) + "It seems like you have not joined the TELLO- or RMTT-network. Please make sure that you have joined the TELLO- or RMTT- Wi-Fi." + ) + elif sys.platform == "darwin": + process = subprocess.Popen( + [ + "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport", + "-I", + ], + stdout=subprocess.PIPE, + ) out, _ = process.communicate() process.wait() - wifi_val = 'Not connected' - for line in out.decode('utf-8').split('\n'): + wifi_val = "Not connected" + for line in out.decode("utf-8").split("\n"): if "SSID: " in line: - _, val = line.split(': ') + _, val = line.split(": ") val = val.strip() wifi_val = val - if 'TELLO-' not in wifi_val or 'RMTT-' not in wifi_val: - logging.debug('Network detected: %s', wifi_val) + if "TELLO-" not in wifi_val or "RMTT-" not in wifi_val: + logging.debug("Network detected: %s", wifi_val) logging.warning( - 'It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') + "It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi." + ) else: - logging.debug('Required network detected: %s', wifi_val) + logging.debug("Required network detected: %s", wifi_val) else: - logging.warning('Could not determine network.') + logging.warning("Could not determine network.") logging.warning( - 'Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks.') + "Make sure that you are connected to the TELLO-XXXXX or RMTT-XXXXX WiFi networks." + ) # Print info to the user - logging.info(' Making UDP socket... \r\n') + logging.info(" Making UDP socket... \r\n") time.sleep(1) # Create UDP socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.tello_address = ('192.168.10.1', 8889) + self.tello_address = ("192.168.10.1", 8889) self.sock.bind(locaddr) - logging.debug('Socket created.') - logging.debug('Socket bound to: %s', str(locaddr)) + logging.debug("Socket created.") + logging.debug("Socket bound to: %s", str(locaddr)) self.recvThread = threading.Thread(target=self.receive) self.recvThread.start() - logging.debug('Receive thread started.') - logging.debug('--------------------------------------\r\n') + logging.debug("Receive thread started.") + logging.debug("--------------------------------------\r\n") # Function to receive commands from the drone def receive(self): @@ -152,11 +159,11 @@ def run(self, command: str, message: str = "No tips available for this command " self.abort = False timer = threading.Timer(10, self._set_abort) # Encode the message in the utf-8 encoding - command = command.encode(encoding='utf-8') + command = command.encode(encoding="utf-8") # Send the encoded message to the Tello self.sent = self.sock.sendto(command, self.tello_address) if self.tips: - print('--:--:-- [TIP] ' + message) + print("--:--:-- [TIP] " + message) self.response = None timer.start() while self.response is None: @@ -164,14 +171,14 @@ def run(self, command: str, message: str = "No tips available for this command " break timer.cancel() if self.response is None: - logging.warning('Command timed out.') - return 'error' + logging.warning("Command timed out.") + return "error" if self.abort is False: - response = self.response.decode(encoding='utf-8') + response = self.response.decode(encoding="utf-8") self.response = None - logging.debug('Response to previous command: %s', response) + logging.debug("Response to previous command: %s", response) return response - return 'error' + return "error" def _set_abort(self): """Sets the abort variable to True""" @@ -180,471 +187,405 @@ def _set_abort(self): # SDK 3.0 Commands def throw_fly(self): """Sends command to the drone to fly when tossed""" - logging.debug('Sending command: throw_fly()') + logging.debug("Sending command: throw_fly()") return self.run( - 'throwfly', - 'Gently toss the drone into the air within 5 seconds!\r\n' + "throwfly", "Gently toss the drone into the air within 5 seconds!\r\n" ) def motors_on(self): """Sends command to turn on motors""" - logging.debug('Sending command: motor_on()') - return self.run( - 'motoron', - 'Turning on motors\r\n' - ) + logging.debug("Sending command: motor_on()") + return self.run("motoron", "Turning on motors\r\n") def motors_off(self): """Sends command to turn off motors""" - logging.debug('Sending command: motor_off()') - return self.run( - 'motoroff', - 'Turning off motors\r\n' - ) + logging.debug("Sending command: motor_off()") + return self.run("motoroff", "Turning off motors\r\n") def reboot(self): """Sends command to reboot the drone""" - logging.debug('Sending command: reboot()') - test = self.run( - 'reboot', - 'Rebooting\r\n' - ) - if test == 'error': - logging.warning('Reboot failed.') - return 'error' - logging.info('Rebooting. Please wait 30 seconds.') - return 'ok' + logging.debug("Sending command: reboot()") + test = self.run("reboot", "Rebooting\r\n") + if test == "error": + logging.warning("Reboot failed.") + return "error" + logging.info("Rebooting. Please wait 30 seconds.") + return "ok" # SDK 3.0 SET Commands def rc(self, roll: int = 0, pitch: int = 0, throttle: int = 0, yaw: int = 0): """Sends command to adjust lever force values (acc. to official docs)""" - logging.debug('Sending command: rc()') - if 100 >= roll >= -100 and 100 >= pitch >= -100 and 100 >= yaw >= -100 and 100 >= throttle >= -100: + logging.debug("Sending command: rc()") + if ( + 100 >= roll >= -100 + and 100 >= pitch >= -100 + and 100 >= yaw >= -100 + and 100 >= throttle >= -100 + ): self.run( - f'rc {roll} {pitch} {throttle} {yaw}', - 'Setting lever force values\r\n' + f"rc {roll} {pitch} {throttle} {yaw}", "Setting lever force values\r\n" ) - return 'ok' - logging.warning('tello.rc(): Invalid value.') - return 'error' + return "ok" + logging.warning("tello.rc(): Invalid value.") + return "error" def set_ap(self, ssid: str, password: str): """Sends command to join access point, then reboot""" - logging.debug('Sending command: ap()') + logging.debug("Sending command: ap()") return self.run( - f'ap {ssid} {password}', - 'Connecting to access point, then rebooting\r\n' + f"ap {ssid} {password}", "Connecting to access point, then rebooting\r\n" ) def set_wifi_channel(self, channel: int): """Sends command to set the WiFi channel""" - logging.debug('Sending command: set_wifi_channel()') + logging.debug("Sending command: set_wifi_channel()") return self.run( - f'wifisetchannel {channel}', - f'Setting Wi-Fi channel to {channel} channel\r\n' + f"wifisetchannel {channel}", + f"Setting Wi-Fi channel to {channel} channel\r\n", ) def set_ports(self, status_port: int, video_port: int): """Sends command to set the ports for status and video""" - logging.debug('Sending command: set_ports()') + logging.debug("Sending command: set_ports()") if 1025 <= status_port <= 65535 and 1025 <= video_port <= 65535: ports = self.run( - f'port {status_port} {video_port}', - 'Setting new ports for status and video\r\n' + f"port {status_port} {video_port}", + "Setting new ports for status and video\r\n", ) - if ports == 'ok': - logging.info('New ports set by client: %s and %s', - status_port, video_port) + if ports == "ok": + logging.info( + "New ports set by client: %s and %s", status_port, video_port + ) # self.info_port = status_port # self.tello_address = ('192.168.10.1', info_port) # # SET VIDEO PORT # - return 'ok' - logging.warning('tello.set_ports(): Failed to set ports.') + return "ok" + logging.warning("tello.set_ports(): Failed to set ports.") logging.debug( - 'Failed to set ports due to an error response from the drone.') - return 'error' - logging.warning('tello.set_ports(): Invalid value.') - return 'error' + "Failed to set ports due to an error response from the drone." + ) + return "error" + logging.warning("tello.set_ports(): Invalid value.") + return "error" def set_fps(self, fps: str): """Sends command to set the video stream frame rate""" - logging.debug('Sending command: set_fps()') - if fps in ('h', 'm', 'l', 'high', 'medium', 'low'): - return self.run( - f'setfps {fps}', - f'Setting FPS to {fps} fps \r\n' - ) - logging.warning('tello.set_fps(): Invalid value.') - return 'error' + logging.debug("Sending command: set_fps()") + if fps in ("h", "m", "l", "high", "medium", "low"): + return self.run(f"setfps {fps}", f"Setting FPS to {fps} fps \r\n") + logging.warning("tello.set_fps(): Invalid value.") + return "error" def set_bitrate(self, bitrate: int): """Sends command to set the video stream bitrate""" - logging.debug('Sending command: set_bitrate()') + logging.debug("Sending command: set_bitrate()") if 1 <= bitrate <= 5: return self.run( - f'setbitrate {bitrate}', - f'Setting bitrate to {bitrate} Mbps\r\n' + f"setbitrate {bitrate}", f"Setting bitrate to {bitrate} Mbps\r\n" ) if bitrate == 0: - return self.run( - f'setbitrate {bitrate}', - 'Setting bitrate to auto\r\n' - ) - logging.warning('tello.set_bitrate(): Invalid value.') - return 'error' + return self.run(f"setbitrate {bitrate}", "Setting bitrate to auto\r\n") + logging.warning("tello.set_bitrate(): Invalid value.") + return "error" def set_resolution(self, resolution: str): """Sends command to set the video stream resolution""" - logging.debug('Sending command: set_resolution()') - if resolution in ('h', 'l', 'high', 'low'): + logging.debug("Sending command: set_resolution()") + if resolution in ("h", "l", "high", "low"): return self.run( - f'setresolution {resolution}', - f'Setting resolution to {resolution} \r\n' + f"setresolution {resolution}", + f"Setting resolution to {resolution} \r\n", ) - logging.warning('tello.set_resolution(): Invalid value.') - return 'error' + logging.warning("tello.set_resolution(): Invalid value.") + return "error" def set_rmtt_wifi(self, ssid: str, password: str): """Sends command to set the RMTT WiFi SSID and password""" - logging.debug('Sending command: set_rmtt_wifi()') + logging.debug("Sending command: set_rmtt_wifi()") return self.run( - f'multwifi {ssid} {password}', - f'Setting RMTT SSID and password to {ssid} {password} \r\n' + f"multwifi {ssid} {password}", + f"Setting RMTT SSID and password to {ssid} {password} \r\n", ) # SDK 2.0 Commands def init(self): """Sends command to initialize SDK mode""" - logging.debug('Sending command: init()') - return self.run( - 'command', - 'Enabling SDK mode\r\n' - ) + logging.debug("Sending command: init()") + return self.run("command", "Enabling SDK mode\r\n") def takeoff(self): """Sends command to take off""" - logging.debug('Sending command: takeoff()') - return self.run( - 'takeoff', - 'Taking off, keep clear of drone!\r\n' - ) + logging.debug("Sending command: takeoff()") + return self.run("takeoff", "Taking off, keep clear of drone!\r\n") def land(self): """Sends command to land""" - logging.debug('Sending command: land()') - return self.run( - 'land', - 'Landing, keep space clear!\r\n' - ) + logging.debug("Sending command: land()") + return self.run("land", "Landing, keep space clear!\r\n") def video_stream_on(self): """Sends command to turn on video stream""" - logging.debug('Sending command: video_stream_on()') - return self.run( - 'streamon', - 'Enabling video stream\r\n' - ) + logging.debug("Sending command: video_stream_on()") + return self.run("streamon", "Enabling video stream\r\n") def video_stream_off(self): """Sends command to turn off video stream""" - logging.debug('Sending command: video_stream_off()') - return self.run( - 'streamoff', - 'Disabling video stream\r\n' - ) + logging.debug("Sending command: video_stream_off()") + return self.run("streamoff", "Disabling video stream\r\n") - def emergency(self, reason='No reason provided'): + def emergency(self, reason="No reason provided"): """Sends command to stop all motors""" - logging.debug('Sending command: emergency()') - self.run( - 'emergency', - 'Emergency stop. Attempting to stop motors.\r\n' - ) - logging.critical('Emergency stop. Exiting script.') + logging.debug("Sending command: emergency()") + self.run("emergency", "Emergency stop. Attempting to stop motors.\r\n") + logging.critical("Emergency stop. Exiting script.") logging.debug( - 'Emergency stop due to: %s. Unable to continue due to motor stop. Exiting.', reason) + "Emergency stop due to: %s. Unable to continue due to motor stop. Exiting.", + reason, + ) sys.exit() def hover(self): """Sends command to stop all movement, hover""" - logging.debug('Sending command: hover()') - return self.run( - 'stop', - 'Stopping all movement, hovering.\r\n' - ) + logging.debug("Sending command: hover()") + return self.run("stop", "Stopping all movement, hovering.\r\n") def up(self, x: int): """Sends command to move up x cm""" - logging.debug('Sending command: up()') + logging.debug("Sending command: up()") if 20 <= x <= 500: return self.run( - f'up {str(x)}', - f'Ascending to {str(x)} cm from the ground \r\n' + f"up {str(x)}", f"Ascending to {str(x)} cm from the ground \r\n" ) - logging.warning('tello.up(): Invalid value.') - return 'error' + logging.warning("tello.up(): Invalid value.") + return "error" def down(self, x: int): """Sends command to move down x cm""" - logging.debug('Sending command: down()') + logging.debug("Sending command: down()") if 20 <= x <= 500: return self.run( - f'down {str(x)}', - f'Descending to {str(x)} cm from the ground \r\n' + f"down {str(x)}", f"Descending to {str(x)} cm from the ground \r\n" ) - logging.warning('tello.down(): Invalid value.') - return 'error' + logging.warning("tello.down(): Invalid value.") + return "error" def left(self, x: int): """Sends command to move left x cm""" - logging.debug('Sending command: left()') + logging.debug("Sending command: left()") if 20 <= x <= 500: return self.run( - f'left {str(x)}', - f'Moving left {str(x)} cm, keep clear of drone\'s path \r\n' + f"left {str(x)}", + f"Moving left {str(x)} cm, keep clear of drone's path \r\n", ) - logging.warning('tello.left(): Invalid value.') - return 'error' + logging.warning("tello.left(): Invalid value.") + return "error" def right(self, x: int): """Sends command to move right x cm""" - logging.debug('Sending command: right()') + logging.debug("Sending command: right()") if 20 <= x <= 500: return self.run( - f'right {str(x)}', - f'Moving right {str(x)} cm, keep clear of drone\'s path \r\n' + f"right {str(x)}", + f"Moving right {str(x)} cm, keep clear of drone's path \r\n", ) - logging.warning('tello.right(): Invalid value.') - return 'error' + logging.warning("tello.right(): Invalid value.") + return "error" def forward(self, x: int): """Sends command to move forward x cm""" - logging.debug('Sending command: forward()') + logging.debug("Sending command: forward()") if 20 <= x <= 500: return self.run( - f'forward {str(x)}', - f'Moving forward {str(x)} cm, keep clear of drone\'s path \r\n' + f"forward {str(x)}", + f"Moving forward {str(x)} cm, keep clear of drone's path \r\n", ) - logging.warning('tello.forward(): Invalid value.') - return 'error' + logging.warning("tello.forward(): Invalid value.") + return "error" def back(self, x: int): """Sends command to move back x cm""" - logging.debug('Sending command: back()') + logging.debug("Sending command: back()") if 20 <= x <= 500: return self.run( - f'back {str(x)}', - f'Moving forward {str(x)} cm, keep clear of drone\'s path \r\n' + f"back {str(x)}", + f"Moving forward {str(x)} cm, keep clear of drone's path \r\n", ) - logging.warning('tello.back(): Invalid value.') - return 'error' + logging.warning("tello.back(): Invalid value.") + return "error" - def rotate(self, direction: str, degrees: int): + def rotate(self, direction: str, degrees: int): """Sends command to rotate clockwise or anti-clockwise for specified amount of degrees""" - logging.debug('Sending command: cw()') + logging.debug("Sending command: cw()") if 1 <= degrees <= 360: - if direction is 'cw': + if direction is "cw": return self.run( - f'cw {str(degrees)}', - f'Rotating clockwise {str(degrees)} degrees \r\n' + f"cw {str(degrees)}", + f"Rotating clockwise {str(degrees)} degrees \r\n", ) - if direction is 'ccw': + if direction is "ccw": return self.run( - f'ccw {str(degrees)}', - f'Rotating counter-clockwise {str(degrees)} degrees \r\n' + f"ccw {str(degrees)}", + f"Rotating counter-clockwise {str(degrees)} degrees \r\n", ) - logging.warning('tello.rotate(): Invalid direction.') - return 'error' - logging.warning('tello.rotate(): Invalid value.') - return 'error' + logging.warning("tello.rotate(): Invalid direction.") + return "error" + logging.warning("tello.rotate(): Invalid value.") + return "error" def flip(self, direction: str): """Sends command to flip in direction specified""" - logging.debug('Sending command: flip()') - if direction in ('l', 'r', 'f', 'b'): + logging.debug("Sending command: flip()") + if direction in ("l", "r", "f", "b"): return self.run( - f'flip {direction}', - f'Flipping {direction}, be careful \r\n' + f"flip {direction}", f"Flipping {direction}, be careful \r\n" ) - logging.warning('tello.flip(): Invalid value.') - return 'error' + logging.warning("tello.flip(): Invalid value.") + return "error" # SET Commands def set_speed(self, x: int): """Sends command to set speed to x cm/s""" - logging.debug('Sending command: set_speed()') + logging.debug("Sending command: set_speed()") if x >= 1 and x <= 100: - return self.run( - f'speed {str(x)}', - f'Setting speed to {str(x)} cm/s \r\n' - ) - logging.warning('tello.set_speed(): Invalid value.') - return 'error' + return self.run(f"speed {str(x)}", f"Setting speed to {str(x)} cm/s \r\n") + logging.warning("tello.set_speed(): Invalid value.") + return "error" def set_wifi(self, ssid: str, passw: str): """Sends command to set wifi ssid and passw""" - logging.debug('Sending command: set_wifi()') - logging.info('SSID: %s, PASSWORD: %s', ssid, passw) + logging.debug("Sending command: set_wifi()") + logging.info("SSID: %s, PASSWORD: %s", ssid, passw) logging.debug( - 'Please note that you will not be able to connect to the drone if you forget this password!') + "Please note that you will not be able to connect to the drone if you forget this password!" + ) return self.run( - f'wifi {ssid}, {passw}', - f'Setting wifi to {ssid}, with password {passw} then rebooting\r\n' + f"wifi {ssid}, {passw}", + f"Setting wifi to {ssid}, with password {passw} then rebooting\r\n", ) def set_mission_on(self): """Sends command to set mission pad detection on""" - logging.debug('Sending command: set_mission_on()') - return self.run( - 'mon', - 'Enabling Mission Pad detection\r\n' - ) + logging.debug("Sending command: set_mission_on()") + return self.run("mon", "Enabling Mission Pad detection\r\n") def set_mission_off(self): """Sends command to set mission pad detection off""" - logging.debug('Sending command: set_mission_off()') - return self.run( - 'moff', - 'Disabling Mission Pad detection\r\n' - ) + logging.debug("Sending command: set_mission_off()") + return self.run("moff", "Disabling Mission Pad detection\r\n") def set_mission_direction(self, x: int): """Sends command to set mission pad detection direction""" - logging.debug('Sending command: set_mission_direction()') + logging.debug("Sending command: set_mission_direction()") if x >= 0 and x <= 3: return self.run( - f'mdirection {str(x)}', - f'Setting Mission Pad Detection to setting {str(x)}\r\n') - logging.warning('tello.set_mission_direction(): Invalid value.') - return 'error' + f"mdirection {str(x)}", + f"Setting Mission Pad Detection to setting {str(x)}\r\n", + ) + logging.warning("tello.set_mission_direction(): Invalid value.") + return "error" # GET Commands def get_speed(self): """Sends command to get speed""" - logging.debug('Sending command: get_speed()') - return self.run( - 'speed?', - 'Obtaining current speed \r\n' - ) + logging.debug("Sending command: get_speed()") + return self.run("speed?", "Obtaining current speed \r\n") def get_battery(self): """Sends command to get battery percentage""" - logging.debug('Sending command: get_battery()') - return self.run( - 'battery?', - 'Obtaining battery level \r\n' - ) + logging.debug("Sending command: get_battery()") + return self.run("battery?", "Obtaining battery level \r\n") def get_flight_time(self): """Sends command to get flight time""" - logging.debug('Sending command: get_time()') - return self.run( - 'time?', - 'Obtaining current flight time \r\n' - ) + logging.debug("Sending command: get_time()") + return self.run("time?", "Obtaining current flight time \r\n") def get_wifi_snr(self): """Sends command to get wifi SNR""" - logging.debug('Sending command: get_wifi_snr()') - return self.run( - 'wifi?', - 'Obtaining WiFi SNR \r\n' - ) + logging.debug("Sending command: get_wifi_snr()") + return self.run("wifi?", "Obtaining WiFi SNR \r\n") def get_sdk(self): """Sends command to get SDK version""" - logging.debug('Sending command: get_sdk()') - return self.run( - 'sdk?', - 'Obtaining Tello SDK Version \r\n' - ) + logging.debug("Sending command: get_sdk()") + return self.run("sdk?", "Obtaining Tello SDK Version \r\n") def get_version(self): """Sends command to get Tello version""" - logging.debug('Sending command: get_version()') - return self.run( - 'version?', - 'Obtaining Tello Version \r\n' - ) + logging.debug("Sending command: get_version()") + return self.run("version?", "Obtaining Tello Version \r\n") def get_sn(self): """Sends command to get serial number""" - logging.debug('Sending command: get_sn()') - return self.run( - 'sn?', - 'Obtaining Tello serial number \r\n' - ) + logging.debug("Sending command: get_sn()") + return self.run("sn?", "Obtaining Tello serial number \r\n") # SDK 3.0 GET Commands def get_hardware(self): """Sends command to get hardware (RMTT or Tello)""" - logging.debug('Sending command: get_hardware()') - return self.run( - 'hardware?', - 'Obtaining hardware status \r\n' - ) + logging.debug("Sending command: get_hardware()") + return self.run("hardware?", "Obtaining hardware status \r\n") def get_rmtt_wifi_version(self): """Sends command to get RMTT WiFi version""" - logging.debug('Sending command: get_rmtt_wifi_version()') - return self.run( - 'wifiversion?', - 'Obtaining RMTT WiFi version \r\n' - ) + logging.debug("Sending command: get_rmtt_wifi_version()") + return self.run("wifiversion?", "Obtaining RMTT WiFi version \r\n") def get_ap(self): """Sends command to get RMTT AP info""" - logging.debug('Sending command: get_ap()') - return self.run( - 'ap?', - 'Obtaining RMTT Access Point SSID and password \r\n' - ) + logging.debug("Sending command: get_ap()") + return self.run("ap?", "Obtaining RMTT Access Point SSID and password \r\n") def get_rmtt_wifi(self): """Sends command to get RMTT SSID""" - logging.debug('Sending command: get_ssid()') - return self.run( - 'ssid?', - 'Obtaining RMTT WiFi SSID and password (if any) \r\n' - ) + logging.debug("Sending command: get_ssid()") + return self.run("ssid?", "Obtaining RMTT WiFi SSID and password (if any) \r\n") # COMPLEX Commands def go(self, x: int, y: int, z: int, s: int): """Sends command to move to x y z at speed s""" - logging.debug('Sending command: go()') + logging.debug("Sending command: go()") if 500 >= x >= -500 and 500 >= y >= -500 and 500 >= z >= -500: if 100 >= s >= 10: return self.run( - f'go {str(x)} {str(y)} {str(z)} {str(z)}', - f'Going to coordinates (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n' + f"go {str(x)} {str(y)} {str(z)} {str(z)}", + f"Going to coordinates (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n", ) - logging.warning('tello.go(): Invalid speed.') - return 'error' - logging.warning('tello.go(): Invalid coordinates.') - return 'error' + logging.warning("tello.go(): Invalid speed.") + return "error" + logging.warning("tello.go(): Invalid coordinates.") + return "error" def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): """Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2""" - logging.debug('Sending command: curve()') - if 500 >= x1 >= -500 and 500 >= x2 >= -500 and 500 >= y1 >= -500 and 500 >= y2 >= -500 and 500 >= z1 >= -500 and 500 >= z2 >= -500: + logging.debug("Sending command: curve()") + if ( + 500 >= x1 >= -500 + and 500 >= x2 >= -500 + and 500 >= y1 >= -500 + and 500 >= y2 >= -500 + and 500 >= z1 >= -500 + and 500 >= z2 >= -500 + ): if 60 >= s >= 10: return self.run( - f'curve {str(x1)} {str(y1)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)}', - f'Curving from (x, y, z): {str(x1)} {str(y1)} {str(z1)} to {str(x2)} {str(y2)} {str(z2)} at the speed of', str( - s), 'cm/s\r\n' + f"curve {str(x1)} {str(y1)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)}", + f"Curving from (x, y, z): {str(x1)} {str(y1)} {str(z1)} to {str(x2)} {str(y2)} {str(z2)} at the speed of", + str(s), + "cm/s\r\n", ) - logging.warning('tello.curve(): Invalid speed.') - return 'error' - logging.warning('tello.curve(): Invalid coordinates.') - return 'error' + logging.warning("tello.curve(): Invalid speed.") + return "error" + logging.warning("tello.curve(): Invalid coordinates.") + return "error" def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): """Sends command to move to mission pad x y z at speed s and find Mpad mid""" - logging.debug('Sending command: go_mission_pad()') + logging.debug("Sending command: go_mission_pad()") mid_ok = False - for id in self.mids.split(' '): + for id in self.mids.split(" "): if id == mid: mid_ok = True break @@ -652,203 +593,212 @@ def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): if 100 >= s >= 10: if mid_ok: return self.run( - f'go {str(x)} {str(y)} {str(z)} {str(s)} {str(mid)}', - f'Going to (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n' + f"go {str(x)} {str(y)} {str(z)} {str(s)} {str(mid)}", + f"Going to (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n", ) - logging.warning( - 'tello.go_mission_pad(): Invalid mission pad ID.') - return 'error' - logging.warning('tello.go_mission_pad(): Invalid speed.') - return 'error' - logging.warning('tello.go_mission_pad(): Invalid coordinates.') - return 'error' - - def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int, mid: str): + logging.warning("tello.go_mission_pad(): Invalid mission pad ID.") + return "error" + logging.warning("tello.go_mission_pad(): Invalid speed.") + return "error" + logging.warning("tello.go_mission_pad(): Invalid coordinates.") + return "error" + + def curve_mission_pad( + self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int, mid: str + ): """Sends command to curve from x y z 1 at speed s to x y z 2 and find Mpad mid""" - logging.debug('Sending command: curve_mission_pad()') + logging.debug("Sending command: curve_mission_pad()") mid_ok = False - for id in self.split(' '): + for id in self.split(" "): if id == mid: mid_ok = True break - if 500 >= x1 >= -500 and 500 >= x2 >= -500 and 500 >= y1 >= -500 and 500 >= y2 >= -500 and 500 >= z1 >= -500 and 500 >= z2 >= -500: + if ( + 500 >= x1 >= -500 + and 500 >= x2 >= -500 + and 500 >= y1 >= -500 + and 500 >= y2 >= -500 + and 500 >= z1 >= -500 + and 500 >= z2 >= -500 + ): if 60 >= s >= 10: if mid_ok: return self.run( - f'curve {str(x1)} {str(x2)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)} {str(mid)}', - f'Curving from (x, y, z): {x1} {y1} {z1} to {x2} {y2} {z2} at the speed of {str(s)} cm/s\r\n' + f"curve {str(x1)} {str(x2)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)} {str(mid)}", + f"Curving from (x, y, z): {x1} {y1} {z1} to {x2} {y2} {z2} at the speed of {str(s)} cm/s\r\n", ) - logging.warning( - 'tello.curve_mission_pad(): Invalid mission pad ID.') - return 'error' - logging.warning('tello.curve_mission_pad(): Invalid speed.') - return 'error' - logging.warning('tello.curve_mission_pad(): Invalid coordinates.') - return 'error' + logging.warning("tello.curve_mission_pad(): Invalid mission pad ID.") + return "error" + logging.warning("tello.curve_mission_pad(): Invalid speed.") + return "error" + logging.warning("tello.curve_mission_pad(): Invalid coordinates.") + return "error" # SDK 3.0 DISPLAY Commands def set_light_off(self): # TO TEST """Sends command to turn off the lights""" - logging.debug('Sending command: set_light_off()') - return self.run( - 'EXT led 0 0 0', - 'Turning off the big light\r\n' - ) + logging.debug("Sending command: set_light_off()") + return self.run("EXT led 0 0 0", "Turning off the big light\r\n") def set_light_color(self, r: int, g: int, b: int): """Sends command to set the color of the LED""" - logging.debug('Sending command: set_light_color()') + logging.debug("Sending command: set_light_color()") if 255 >= r >= 0 and 255 >= g >= 0 and 255 >= b >= 0: return self.run( - f'EXT led {str(r)} {str(g)} {str(b)}', - f'Setting RMTT light color to (r, g, b): {str(r)}, {str(g)}, {str(b)}\r\n' + f"EXT led {str(r)} {str(g)} {str(b)}", + f"Setting RMTT light color to (r, g, b): {str(r)}, {str(g)}, {str(b)}\r\n", ) - logging.warning('tello.set_light_color(): Invalid color.') - return 'led error' + logging.warning("tello.set_light_color(): Invalid color.") + return "led error" def set_light_pulse(self, r: int, g: int, b: int, p: float or int): """Sends command to set the color of the LED and pulse""" - logging.debug('Sending command: set_light_pulse()') + logging.debug("Sending command: set_light_pulse()") if 255 >= r >= 0 and 255 >= g >= 0 and 255 >= b >= 0 and 2.5 >= p >= 0.1: return self.run( - f'EXT led br {str(p)} {str(r)} {str(g)} {str(b)}', - f'Setting RMTT light color to (r, g, b):, {str(r)}, {str(g)}, {str(b)}, with pulse of, {str(p)} Hz\r\n' + f"EXT led br {str(p)} {str(r)} {str(g)} {str(b)}", + f"Setting RMTT light color to (r, g, b):, {str(r)}, {str(g)}, {str(b)}, with pulse of, {str(p)} Hz\r\n", ) - logging.warning('tello.set_light_pulse(): Invalid values.') - return 'led error' + logging.warning("tello.set_light_pulse(): Invalid values.") + return "led error" - def set_light_flash(self, r1: int, g1: int, b1: int, r2: int, g2: int, b2: int, f: float or int): + def set_light_flash( + self, r1: int, g1: int, b1: int, r2: int, g2: int, b2: int, f: float or int + ): """Sends command to set the 2 colors of the LED to flash""" - logging.debug('Sending command: set_light_flash()') - if 255 >= r1 >= 0 and 255 >= g1 >= 0 and 255 >= b1 >= 0 and 255 >= r2 >= 0 and 255 >= g2 >= 0 and 255 >= b2 >= 0 and 2.5 >= f >= 0.1: + logging.debug("Sending command: set_light_flash()") + if ( + 255 >= r1 >= 0 + and 255 >= g1 >= 0 + and 255 >= b1 >= 0 + and 255 >= r2 >= 0 + and 255 >= g2 >= 0 + and 255 >= b2 >= 0 + and 2.5 >= f >= 0.1 + ): return self.run( - f'EXT led bl {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}', - f'Setting RMTT light color to (r, g, b): {str(r1)}, {str(g1)}, {str(b1)} and {str(r2)}, {str(g2)}, {str(b2)} with flash of {str(f)} Hz\r\n' + f"EXT led bl {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}", + f"Setting RMTT light color to (r, g, b): {str(r1)}, {str(g1)}, {str(b1)} and {str(r2)}, {str(g2)}, {str(b2)} with flash of {str(f)} Hz\r\n", ) - logging.warning('tello.set_light_flash(): Invalid values.') - return 'led error' + logging.warning("tello.set_light_flash(): Invalid values.") + return "led error" - def set_display_pattern(self, pattern: str = '0'): + def set_display_pattern(self, pattern: str = "0"): """Sends command to set the display pattern""" - logging.debug('Sending command: set_display_pattern()') + logging.debug("Sending command: set_display_pattern()") for char in pattern: - if char not in 'rbp0': - logging.warning( - 'tello.set_display_pattern(): Invalid pattern.') - return 'matrix error' + if char not in "rbp0": + logging.warning("tello.set_display_pattern(): Invalid pattern.") + return "matrix error" return self.run( - f'EXT mled g {str(pattern)}', - f'Setting RMTT display pattern to: {str(pattern)} \r\n' + f"EXT mled g {str(pattern)}", + f"Setting RMTT display pattern to: {str(pattern)} \r\n", ) def set_display_blank(self): # TO TEST """Sends command to make the display blank""" - logging.debug('Sending command: set_display_off()') + logging.debug("Sending command: set_display_off()") return self.run( - 'EXT mled g 0000000000000000000000000000000000000000000000000000000000000000', - 'Turning off the display\r\n' + "EXT mled g 0000000000000000000000000000000000000000000000000000000000000000", + "Turning off the display\r\n", ) - def set_display_string(self, direction: str, color: str, frame_rate: float or int, string: str): + def set_display_string( + self, direction: str, color: str, frame_rate: float or int, string: str + ): """Sends command to show a string on the display""" - logging.debug('Sending command: set_display_string()') + logging.debug("Sending command: set_display_string()") for char in direction: - if char not in 'lrud': - logging.warning( - 'tello.set_display_string(): Invalid direction.') - return 'matrix error' - if color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1: + if char not in "lrud": + logging.warning("tello.set_display_string(): Invalid direction.") + return "matrix error" + if color in ("r", "b", "p") and 10 >= frame_rate >= 0.1: return self.run( - f'EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(string)}', - f'Showing the string: {str(string)} with color: {str(color)}, frame rate (Hz): {str(frame_rate)} and in the diretion: {str(direction)} on the RMTT display \r\n' + f"EXT mled {str(direction)} {str(color)} {str(frame_rate)} {str(string)}", + f"Showing the string: {str(string)} with color: {str(color)}, frame rate (Hz): {str(frame_rate)} and in the diretion: {str(direction)} on the RMTT display \r\n", ) - logging.warning('tello.set_display_string(): Invalid values.') - return 'matrix error' + logging.warning("tello.set_display_string(): Invalid values.") + return "matrix error" - def set_display_moving_image(self, direction: str, color: str, frame_rate: float or int, pattern: str): + def set_display_moving_image( + self, direction: str, color: str, frame_rate: float or int, pattern: str + ): """Sends command to show a moving image on the display""" - logging.debug('Sending command: set_display_moving_image()') + logging.debug("Sending command: set_display_moving_image()") for char in direction: - if char not in 'lrud': - logging.warning( - 'tello.set_display_moving_image(): Invalid direction.') - return 'matrix error' + if char not in "lrud": + logging.warning("tello.set_display_moving_image(): Invalid direction.") + return "matrix error" for char in pattern: - if char not in 'rbp0': - logging.warning( - 'tello.set_display_moving_image(): Invalid pattern.') - return 'matrix error' - if color in ('r', 'b', 'p') and 10 >= frame_rate >= 0.1: + if char not in "rbp0": + logging.warning("tello.set_display_moving_image(): Invalid pattern.") + return "matrix error" + if color in ("r", "b", "p") and 10 >= frame_rate >= 0.1: return self.run( - f'EXT mled {str(direction)} g {str(frame_rate)} {str(pattern)}', - f'Showing a moving image on the RMTT display in the direction: {str(direction)} with color: {str(color)}, frame rate (Hz): {str(frame_rate)} and pattern: {str(pattern)} \r\n' + f"EXT mled {str(direction)} g {str(frame_rate)} {str(pattern)}", + f"Showing a moving image on the RMTT display in the direction: {str(direction)} with color: {str(color)}, frame rate (Hz): {str(frame_rate)} and pattern: {str(pattern)} \r\n", ) - logging.warning('tello.set_display_moving_image(): Invalid values.') - return 'matrix error' + logging.warning("tello.set_display_moving_image(): Invalid values.") + return "matrix error" def set_display_ascii_character(self, character: str, color: str): # TEST """Sends command to display ascii character""" - logging.debug('Sending command: set_display_ascii_character()') - if character == 'heart' or character.encode('ascii') and color in ('r', 'b', 'p'): + logging.debug("Sending command: set_display_ascii_character()") + if ( + character == "heart" + or character.encode("ascii") + and color in ("r", "b", "p") + ): return self.run( # TEST f'EXT mled s {str(color)} {str(character.encode("ascii"))}', - f'Displaying ASCII character: {str(character)} with color: {str(color)} \r\n' + f"Displaying ASCII character: {str(character)} with color: {str(color)} \r\n", ) - logging.warning('tello.set_display_ascii_character(): Invalid values.') - return 'matrix error' + logging.warning("tello.set_display_ascii_character(): Invalid values.") + return "matrix error" def set_display_boot(self, pattern: str): """Sends command to set the display boot pattern""" - logging.debug('Sending command: set_display_boot()') + logging.debug("Sending command: set_display_boot()") for char in pattern: - if char not in 'rbp0': - logging.warning('tello.set_display_boot(): Invalid pattern.') - return 'error' + if char not in "rbp0": + logging.warning("tello.set_display_boot(): Invalid pattern.") + return "error" return self.run( - f'EXT mled sg {str(pattern)}', - f'Setting RMTT boot display pattern to: {str(pattern)} \r\n' + f"EXT mled sg {str(pattern)}", + f"Setting RMTT boot display pattern to: {str(pattern)} \r\n", ) def clear_display_boot(self): """Sends command to clear the display boot pattern""" - logging.debug('Sending command: clear_display_boot()') - return self.run( - 'EXT mled sc', - 'Clearing RMTT boot display pattern\r\n' - ) + logging.debug("Sending command: clear_display_boot()") + return self.run("EXT mled sc", "Clearing RMTT boot display pattern\r\n") def set_display_brightness(self, brightness: int): """Sends command to set the display brightness""" - logging.debug('Sending command: set_display_brightness()') + logging.debug("Sending command: set_display_brightness()") if 255 >= brightness >= 0: return self.run( - f'EXT mled sl {str(brightness)}', - f'Setting RMTT display brightness to: {str(brightness)} \r\n' + f"EXT mled sl {str(brightness)}", + f"Setting RMTT display brightness to: {str(brightness)} \r\n", ) - logging.warning('tello.set_display_brightness(): Invalid brightness.') - return 'matrix error' + logging.warning("tello.set_display_brightness(): Invalid brightness.") + return "matrix error" def get_tof(self): """Sends command to get the distance from the drone to the nearest obstacle in front""" - logging.debug('Sending command: get_tof()') - return self.run( - 'EXT tof?', - 'Getting ToF (read docs for more info)...\r\n' - ) + logging.debug("Sending command: get_tof()") + return self.run("EXT tof?", "Getting ToF (read docs for more info)...\r\n") def get_esp32_version(self): """Sends command to get the ESP32 version""" - logging.debug('Sending command: get_esp32_version()') - return self.run( - 'EXT version?', - 'Getting RMTT version...\r\n' - ) + logging.debug("Sending command: get_esp32_version()") + return self.run("EXT version?", "Getting RMTT version...\r\n") # End command def end(self): """Closes the socket""" - logging.debug('end(): Closing socket') + logging.debug("end(): Closing socket") self.sock.close() - logging.debug('end(): Socket closed') - return 'ok' + logging.debug("end(): Socket closed") + return "ok" diff --git a/tello_sdk/telloLive.py b/tello_sdk/telloLive.py index 6755d93..5b5f467 100644 --- a/tello_sdk/telloLive.py +++ b/tello_sdk/telloLive.py @@ -7,65 +7,69 @@ import time import subprocess -host = '' +host = "" port = 9000 locaddr = (host, port) # Print general info for the user -print('_________ ____ ____ ') -print(' | | | | | |') -print(' | |___ | | | |') -print(' | | | | | |') -print(' | |____ |____ |____ |____|\r\n') -print(' Drone Script ') -print(' Live editing edition! \r\n') +print("_________ ____ ____ ") +print(" | | | | | |") +print(" | |___ | | | |") +print(" | | | | | |") +print(" | |____ |____ |____ |____|\r\n") +print(" Drone Script ") +print(" Live editing edition! \r\n") time.sleep(0.5) -print(' Initializing... \r\n') +print(" Initializing... \r\n") time.sleep(1) -print(' Checking network... \r\n') +print(" Checking network... \r\n") time.sleep(1) try: - process = subprocess.Popen([ - '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', - '-I' - ], stdout=subprocess.PIPE) + process = subprocess.Popen( + [ + "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport", + "-I", + ], + stdout=subprocess.PIPE, + ) out, err = process.communicate() process.wait() wifi_val = {} - for line in out.decode('utf-8').split('\n'): + for line in out.decode("utf-8").split("\n"): if "SSID: " in line: - key, val = line.split(': ') + key, val = line.split(": ") val = val.strip() wifi_val = val - if 'TELLO-' not in wifi_val: - print('Network detected:', wifi_val) - print('It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi.') - approval = input( - "Are you sure you want to continue with the script? (y/n)") - if approval == 'y': - print('\r\n') + if "TELLO-" not in wifi_val: + print("Network detected:", wifi_val) + print( + "It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi." + ) + approval = input("Are you sure you want to continue with the script? (y/n)") + if approval == "y": + print("\r\n") else: sys.exit() else: - print('Network detected:', wifi_val) - print('No errors. \r\n') + print("Network detected:", wifi_val) + print("No errors. \r\n") except subprocess.SubprocessError: - print('\r\nSeems like there was an error checking the network.') - print('Continuing.\r\n') + print("\r\nSeems like there was an error checking the network.") + print("Continuing.\r\n") -print(' Making UDP socket... \r\n') +print(" Making UDP socket... \r\n") time.sleep(1) # Create a UDP socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -tello_address = ('192.168.10.1', 8889) +tello_address = ("192.168.10.1", 8889) sock.bind(locaddr) @@ -76,27 +80,31 @@ def recv(): while True: try: data, _ = sock.recvfrom(1518) - data = data.decode(encoding='utf-8') - if data == 'ok': - print('Operation successful\r\n') - elif 'error' in data: + data = data.decode(encoding="utf-8") + if data == "ok": + print("Operation successful\r\n") + elif "error" in data: print(data) else: - print('Next time, try writing something valid!') + print("Next time, try writing something valid!") print(data) except Exception: - print('\nExiting...\n') + print("\nExiting...\n") break -print("\r\nTo view all available functions, type", - '\033[1m' + 'help' + '\033[0m') -print("\r\nTo quit the script, type", '\033[1m' + 'end' + '\033[0m') -print("\r\n(For emergencies) To immediately quit the script, press", - '\033[1m' + 'Ctrl + C' + '\033[0m') -print("\r\nIMPORTANT! Do", '\033[1m' + 'not' + - '\033[0m', 'type until a response is received!') -print("\r\nTo begin, type", '\033[1m' + 'command' + '\033[0m: \r\n') +print("\r\nTo view all available functions, type", "\033[1m" + "help" + "\033[0m") +print("\r\nTo quit the script, type", "\033[1m" + "end" + "\033[0m") +print( + "\r\n(For emergencies) To immediately quit the script, press", + "\033[1m" + "Ctrl + C" + "\033[0m", +) +print( + "\r\nIMPORTANT! Do", + "\033[1m" + "not" + "\033[0m", + "type until a response is received!", +) +print("\r\nTo begin, type", "\033[1m" + "command" + "\033[0m: \r\n") # recvThread create @@ -113,83 +121,103 @@ def recv(): break # Ending functionality (when typed 'end') - if msg == 'end': - print('...') - print('Make sure the drone has fully landed! \r\n') + if msg == "end": + print("...") + print("Make sure the drone has fully landed! \r\n") endmsg = input("Continue? (y/n)") if endmsg == "y": sock.close() break - print('OK\r\n') + print("OK\r\n") # Help functionality (when typed 'help') - elif msg == 'help': - print('\r\nSimple functions:') - print(' command -- Initiate SDK mode (first command)') - print(' takeoff -- Automatic takeoff') - print(' land -- Automatic landing') - print(' streamon -- Enable video stream') - print(' streamoff -- Disable video stream') - print(' emergency -- Stop motors immediately') - print(' up/down x -- Ascend/descend to x cm (20-500)') + elif msg == "help": + print("\r\nSimple functions:") + print(" command -- Initiate SDK mode (first command)") + print(" takeoff -- Automatic takeoff") + print(" land -- Automatic landing") + print(" streamon -- Enable video stream") + print(" streamoff -- Disable video stream") + print(" emergency -- Stop motors immediately") + print(" up/down x -- Ascend/descend to x cm (20-500)") print( - ' left/right/forward/back x -- Fly forward/backward/left/right for x cm (20-500)') - print(' cw/ccw x -- Rotate clockwise/counterclockwise x degrees (1-360)') + " left/right/forward/back x -- Fly forward/backward/left/right for x cm (20-500)" + ) print( - ' flip x -- Flip in the x direction (l (left), r (right), f (forw.), b (backw.))') - print(' stop -- Hover in the air') - print('\r\nTo view set, read and hard functions, type \'help set\', \'help read\' or \'help hard\' \r\n\r\n') - elif msg == 'help hard': - print('\r\nHard functions:') - print(' go x y z s -- Fly to x y z at speed s') - print(' x = left to right (500 to -500)') - print(' y = forwards, backwards (-500 to 500)') - print(' z = up, down (-500 to 500)') - print(' s = cm/s (10 to 100)') - print(' curve x1 y1 z1 x2 y2 z2 s -- Fly at a curve (make corner from coordinates) at s speed (arc radius must be between 0.5m and 10m)') - print(' x1, x2 = left, right (-500 to 500)') - print(' y1, y2 = forwards, backwards (-500 to 500)') - print(' z1, z2 = up, down (-500 to 500)') - print(' s = cm/s (10 to 60)') - print(' go x y z s mid -- Fly to x y z at speed s of the mission pad') - print(' x = left, right (-500 to 500)') - print(' y = forwards, backwards (-500 to 500)') - print(' z = up, down (-500 to 500)') - print(' s = cm/s (10 to 100)') - print(' mid1, mid2 = mission pad id (m1 to m8)') - print(' curve x1 y1 z1 x2 y2 z2 s mid -- Fly at a curve (make corner from coordinates) at s speed (arc radius must be between 0.5m and 10m) of the mission pad') - print(' x1, x2 = left, right (-500 to 500)') - print(' y1, y2 = forwards, backwards (-500 to 500)') - print(' z1, z2 = up, down (-500 to 500)') - print(' s = cm/s (10 to 60)') - print(' jump x y z s yaw mid1 mid2 -- Fly to x, y, z of mid1 and recognize 0, 0, z of mid2 and rotate yaw') - print(' x = left, right (-500 to 500)') - print(' y = forwards, backwards (-500 to 500)') - print(' z = up, down (-500 to 500)') - print(' s = cm/s (10 to 100)') - print(' mid1, mid2 = ?? (m1 to m8)') - print('\r\nTo view set, read and hard functions, type \'help set\', \'help read\' or \'help hard\' \r\n\r\n') - elif msg == 'help set': - print('\r\nSet commands:') - print(' speed x -- Set speed to x (10 to 100 cm/s)') - print(' wifi name pass -- Set Wi-Fi ssid to name and password to pass') - print(' mon -- Enable mission pad detection') - print(' moff -- Disable mission pad detection') - print(' mdirection x -- Sets mission pad detection to x: either downward (0), forward (1), or both (2)') - print('\r\nTo view set, read and hard functions, type \'help set\', \'help read\' or \'help hard\' \r\n\r\n') - elif msg == 'help read': - print('\r\nRead commands:') - print(' speed? -- Obtain current set speed (10 to 100 cm/s)') - print(' battey? -- Obtain battery percentage (0 to 100)') - print(' time? -- Obtain current flight time') - print(' wifi? -- Obtain current Wi-Fi SNR') - print(' sdk? -- Obtain current Tello SDK version') - print(' sn? -- Obtain current Tello serial number') - print('\r\nTo view set, read and hard functions, type \'help set\', \'help read\' or \'help hard\' \r\n\r\n') + " cw/ccw x -- Rotate clockwise/counterclockwise x degrees (1-360)" + ) + print( + " flip x -- Flip in the x direction (l (left), r (right), f (forw.), b (backw.))" + ) + print(" stop -- Hover in the air") + print( + "\r\nTo view set, read and hard functions, type 'help set', 'help read' or 'help hard' \r\n\r\n" + ) + elif msg == "help hard": + print("\r\nHard functions:") + print(" go x y z s -- Fly to x y z at speed s") + print(" x = left to right (500 to -500)") + print(" y = forwards, backwards (-500 to 500)") + print(" z = up, down (-500 to 500)") + print(" s = cm/s (10 to 100)") + print( + " curve x1 y1 z1 x2 y2 z2 s -- Fly at a curve (make corner from coordinates) at s speed (arc radius must be between 0.5m and 10m)" + ) + print(" x1, x2 = left, right (-500 to 500)") + print(" y1, y2 = forwards, backwards (-500 to 500)") + print(" z1, z2 = up, down (-500 to 500)") + print(" s = cm/s (10 to 60)") + print(" go x y z s mid -- Fly to x y z at speed s of the mission pad") + print(" x = left, right (-500 to 500)") + print(" y = forwards, backwards (-500 to 500)") + print(" z = up, down (-500 to 500)") + print(" s = cm/s (10 to 100)") + print(" mid1, mid2 = mission pad id (m1 to m8)") + print( + " curve x1 y1 z1 x2 y2 z2 s mid -- Fly at a curve (make corner from coordinates) at s speed (arc radius must be between 0.5m and 10m) of the mission pad" + ) + print(" x1, x2 = left, right (-500 to 500)") + print(" y1, y2 = forwards, backwards (-500 to 500)") + print(" z1, z2 = up, down (-500 to 500)") + print(" s = cm/s (10 to 60)") + print( + " jump x y z s yaw mid1 mid2 -- Fly to x, y, z of mid1 and recognize 0, 0, z of mid2 and rotate yaw" + ) + print(" x = left, right (-500 to 500)") + print(" y = forwards, backwards (-500 to 500)") + print(" z = up, down (-500 to 500)") + print(" s = cm/s (10 to 100)") + print(" mid1, mid2 = ?? (m1 to m8)") + print( + "\r\nTo view set, read and hard functions, type 'help set', 'help read' or 'help hard' \r\n\r\n" + ) + elif msg == "help set": + print("\r\nSet commands:") + print(" speed x -- Set speed to x (10 to 100 cm/s)") + print(" wifi name pass -- Set Wi-Fi ssid to name and password to pass") + print(" mon -- Enable mission pad detection") + print(" moff -- Disable mission pad detection") + print( + " mdirection x -- Sets mission pad detection to x: either downward (0), forward (1), or both (2)" + ) + print( + "\r\nTo view set, read and hard functions, type 'help set', 'help read' or 'help hard' \r\n\r\n" + ) + elif msg == "help read": + print("\r\nRead commands:") + print(" speed? -- Obtain current set speed (10 to 100 cm/s)") + print(" battey? -- Obtain battery percentage (0 to 100)") + print(" time? -- Obtain current flight time") + print(" wifi? -- Obtain current Wi-Fi SNR") + print(" sdk? -- Obtain current Tello SDK version") + print(" sn? -- Obtain current Tello serial number") + print( + "\r\nTo view set, read and hard functions, type 'help set', 'help read' or 'help hard' \r\n\r\n" + ) else: # Send data msg = msg.encode(encoding="utf-8") sent = sock.sendto(msg, tello_address) except KeyboardInterrupt: - print('\n . . .\n') + print("\n . . .\n") sock.close() break From 45d8375ae9a6b4c2dc05389bd3e92c77e0006630 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 9 Nov 2022 10:56:45 +0000 Subject: [PATCH 14/18] Restyled by isort --- setup.py | 2 +- tello_sdk/tello.py | 9 +++++---- tello_sdk/telloLive.py | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index 7121111..cb62707 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup, find_packages +from setuptools import find_packages, setup def readme(): diff --git a/tello_sdk/tello.py b/tello_sdk/tello.py index 6ccb783..fc09da5 100644 --- a/tello_sdk/tello.py +++ b/tello_sdk/tello.py @@ -1,14 +1,15 @@ # !! tello.curveMpad() -- ERROR: RUN TIMEOUT ??? # Import all needed libraries -import string +import logging import socket +import string +import subprocess import sys -import time import threading -import subprocess +import time + import sentry_sdk -import logging # Initialize Sentry (error catching) # Delete the following 4 lines to opt out diff --git a/tello_sdk/telloLive.py b/tello_sdk/telloLive.py index 5b5f467..2628782 100644 --- a/tello_sdk/telloLive.py +++ b/tello_sdk/telloLive.py @@ -1,11 +1,11 @@ # Support for this has ended. This will no lonegr be updated. # A new real-time Tello control script is coming soon -import threading import socket +import subprocess import sys +import threading import time -import subprocess host = "" port = 9000 From f878c5c3502ca32398b5ca1787c2fe0a94867267 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 9 Nov 2022 10:56:46 +0000 Subject: [PATCH 15/18] Restyled by prettier-markdown --- README.md | 17 +++++++--- VERSIONS.md | 93 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 04844cc..bbfb93b 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,43 @@ # Python Tello + This is a library for easy usage of the Ryze Tello drone education edition and RoboMaster Tello Talent. Beginner Friendly!
**Current Version:** -*2.4.1*
+_2.4.1_
SDK 3.0 is **here** and **tested**! + ## Requirements: -* Python 3.6 or higher installed on your system (get it on [python.org](https://www.python.org/)) -* Ryze Tello EDU Edition (get one [here](https://www.ryzerobotics.com/tello-edu)) OR RoboMaster Tello Talent (get one [here](https://store.dji.com/product/robomaster-tt)) -* This package +- Python 3.6 or higher installed on your system (get it on [python.org](https://www.python.org/)) +- Ryze Tello EDU Edition (get one [here](https://www.ryzerobotics.com/tello-edu)) OR RoboMaster Tello Talent (get one [here](https://store.dji.com/product/robomaster-tt)) +- This package ## Documentation + To see the documentation, please go to the GitHub Wiki of this project, available [here](https://github.com/ErnGusMik/python-tello/wiki) ## Getting Started + You can get this package on PyPi (pip) and GitHub. To donwload using GitHub, please click [this link](https://github.com/ErnGusMik/python-tello/archive/refs/heads/main.zip). The package will start downloading. To download using pip, enter the following in your terminal interface (Command Prompt on Windows): + ```bash user@os$ pip install tello-sdk ``` + [More info in the Docs](https://github.com/ErnGusMik/python-tello/wiki) ## Usage + The library is beginner friendly. Even if you are new to programming, usage should be easy. The Tello SDK library is made of callable functions that make the drone do something. [For function names, refer to the Docs](https://github.com/ErnGusMik/python-tello/wiki) ## Contributors + This library was created entirely by ErnGusMik ## Licence + This library is licenced under the MIT licence. diff --git a/VERSIONS.md b/VERSIONS.md index 5d8adde..7b51392 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -1,69 +1,80 @@ # Tello & RMTT SDK + ## Version history: + **2.4.1** -* Documentation finished -* Redone README.md -* Added VERSIONS.md + +- Documentation finished +- Redone README.md +- Added VERSIONS.md **2.3.0-alpha** -* Naming changes -* Added tello_version() -* Did research. + +- Naming changes +- Added tello_version() +- Did research. **2.1.0-alpha** -* Tested all new EXT commands -* Tested most other new commands -* setup.py changes (long-description) -* deepsource.toml changes (max-line-limt: 100) -* tello.set_display_ascii_character() is still being tested. + +- Tested all new EXT commands +- Tested most other new commands +- setup.py changes (long-description) +- deepsource.toml changes (max-line-limt: 100) +- tello.set_display_ascii_character() is still being tested. **2.0.5-alpha** -* setup.py changes -* Re-releasing on pip + +- setup.py changes +- Re-releasing on pip **2.0.4-alpha** -* Readded .deepsource.toml -* Hopefully fixed pip 'No Description provided' issue + +- Readded .deepsource.toml +- Hopefully fixed pip 'No Description provided' issue **2.0.3-alpha** -* Reorganized structure for PyPi -* Added LICENSE.txt (MIT License) -* Added setup.cfg -* Added setup.py and configured for PyPi -* Added tello-sdk/__init__.py -* We're pip installable now! + +- Reorganized structure for PyPi +- Added LICENSE.txt (MIT License) +- Added setup.cfg +- Added setup.py and configured for PyPi +- Added tello-sdk/**init**.py +- We're pip installable now! **2.0.2-alpha** -* Style fixes -* Started work on going pip-ready :) -* Changed all print to logging (for easier debugging) -* Added debugging and tips options to Tello class + +- Style fixes +- Started work on going pip-ready :) +- Changed all print to logging (for easier debugging) +- Added debugging and tips options to Tello class **2.0.1-alpha** -* Small fixes + +- Small fixes **2.0-alpha** -* All new Tello SDK 3.0 commands implemented! -* Small potential bug/style fixes -* This is an Alpha version, so it is **not** stable, by any means! +- All new Tello SDK 3.0 commands implemented! +- Small potential bug/style fixes +- This is an Alpha version, so it is **not** stable, by any means! **1.1.2-alpha** -* Potential bug fixes -* Security issue fix -* Performance optimizations -* Remodel of __init__ function +- Potential bug fixes +- Security issue fix +- Performance optimizations +- Remodel of **init** function **1.1-beta:** -* Implementation of some Tello SDK 3.0 commands -* Naming changes -* Functions now return the response -* In development: camera functions, customization, SDK 3.0 full implementation -* V1.1.1: spelling fix +- Implementation of some Tello SDK 3.0 commands +- Naming changes +- Functions now return the response +- In development: camera functions, customization, SDK 3.0 full implementation +- V1.1.1: spelling fix **1.0-beta:** -* Implement most of Tello SDK 2.0 commands -* Documentation started -* `tello.run()` command for executing any command straight to the drone. \ No newline at end of file + +- Implement most of Tello SDK 2.0 commands +- Documentation started +- `tello.run()` command for executing any command straight to the drone. From 90798304e07a4ff744aff12a25e3e15077811227 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 9 Nov 2022 10:56:50 +0000 Subject: [PATCH 16/18] Restyled by reorder-python-imports --- setup.py | 3 ++- tello_sdk/tello.py | 1 - tello_sdk/telloLive.py | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index cb62707..973da06 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,5 @@ -from setuptools import find_packages, setup +from setuptools import find_packages +from setuptools import setup def readme(): diff --git a/tello_sdk/tello.py b/tello_sdk/tello.py index fc09da5..851d048 100644 --- a/tello_sdk/tello.py +++ b/tello_sdk/tello.py @@ -1,5 +1,4 @@ # !! tello.curveMpad() -- ERROR: RUN TIMEOUT ??? - # Import all needed libraries import logging import socket diff --git a/tello_sdk/telloLive.py b/tello_sdk/telloLive.py index 2628782..d7b592c 100644 --- a/tello_sdk/telloLive.py +++ b/tello_sdk/telloLive.py @@ -1,6 +1,5 @@ # Support for this has ended. This will no lonegr be updated. # A new real-time Tello control script is coming soon - import socket import subprocess import sys From 3dc1aa37cb37adc1a6e8b18e55290c9f2bb1d86c Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 9 Nov 2022 10:56:51 +0000 Subject: [PATCH 17/18] Restyled by whitespace --- LICENCE | 2 +- MANIFEST.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENCE b/LICENCE index c0d3a7d..33294a4 100644 --- a/LICENCE +++ b/LICENCE @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in index 4bf4483..bb3ec5f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -include README.md \ No newline at end of file +include README.md From b7f3147851070fa78274d474c54bf24e2e368145 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 9 Nov 2022 10:56:53 +0000 Subject: [PATCH 18/18] Restyled by yapf --- setup.py | 6 +- tello_sdk/tello.py | 167 +++++++++++++++++++---------------------- tello_sdk/telloLive.py | 28 ++++--- 3 files changed, 96 insertions(+), 105 deletions(-) diff --git a/setup.py b/setup.py index 973da06..599352b 100644 --- a/setup.py +++ b/setup.py @@ -12,11 +12,13 @@ def readme(): packages=find_packages("tello_sdk"), version="2.4.1", license="MIT", - description="Python SDK fro the Tello EDU and RMTT drones, with all commands and more.", + description= + "Python SDK fro the Tello EDU and RMTT drones, with all commands and more.", author="ErnGusMik", author_email="ernests.mikuts@gmail.com", url="https://github.com/ErnGusMik/python-tello", - download_url="https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.1.0-alpha.tar.gz", + download_url= + "https://github.com/ErnGusMik/python-tello/archive/refs/tags/v2.1.0-alpha.tar.gz", keywords=[ "tello", "drone", diff --git a/tello_sdk/tello.py b/tello_sdk/tello.py index 851d048..b431ccf 100644 --- a/tello_sdk/tello.py +++ b/tello_sdk/tello.py @@ -16,9 +16,11 @@ # ------------------ # sentry_sdk.init( - dsn="https://f2fcaa10be4f41958ab756183583ba81@o1400261.ingest.sentry.io/6728983", + dsn= + "https://f2fcaa10be4f41958ab756183583ba81@o1400261.ingest.sentry.io/6728983", traces_sample_rate=1.0, ) + # ------------------ # @@ -84,8 +86,7 @@ def __init__(self, log_in_console: bool = True, tips: bool = True): # Check what network is connected if sys.platform == "win32": wifi = subprocess.check_output( - ["/windows/system32/netsh", "WLAN", "show", "interfaces"] - ) + ["/windows/system32/netsh", "WLAN", "show", "interfaces"]) data = wifi.decode("utf-8") wifi_val = "Not connected" for line in data.split("\n"): @@ -154,7 +155,9 @@ def receive(self): except Exception: break - def run(self, command: str, message: str = "No tips available for this command "): + def run(self, + command: str, + message: str = "No tips available for this command "): """Sends command to the drone and prints message to the user""" self.abort = False timer = threading.Timer(10, self._set_abort) @@ -189,8 +192,8 @@ def throw_fly(self): """Sends command to the drone to fly when tossed""" logging.debug("Sending command: throw_fly()") return self.run( - "throwfly", "Gently toss the drone into the air within 5 seconds!\r\n" - ) + "throwfly", + "Gently toss the drone into the air within 5 seconds!\r\n") def motors_on(self): """Sends command to turn on motors""" @@ -213,18 +216,17 @@ def reboot(self): return "ok" # SDK 3.0 SET Commands - def rc(self, roll: int = 0, pitch: int = 0, throttle: int = 0, yaw: int = 0): + def rc(self, + roll: int = 0, + pitch: int = 0, + throttle: int = 0, + yaw: int = 0): """Sends command to adjust lever force values (acc. to official docs)""" logging.debug("Sending command: rc()") - if ( - 100 >= roll >= -100 - and 100 >= pitch >= -100 - and 100 >= yaw >= -100 - and 100 >= throttle >= -100 - ): - self.run( - f"rc {roll} {pitch} {throttle} {yaw}", "Setting lever force values\r\n" - ) + if (100 >= roll >= -100 and 100 >= pitch >= -100 and 100 >= yaw >= -100 + and 100 >= throttle >= -100): + self.run(f"rc {roll} {pitch} {throttle} {yaw}", + "Setting lever force values\r\n") return "ok" logging.warning("tello.rc(): Invalid value.") return "error" @@ -232,9 +234,8 @@ def rc(self, roll: int = 0, pitch: int = 0, throttle: int = 0, yaw: int = 0): def set_ap(self, ssid: str, password: str): """Sends command to join access point, then reboot""" logging.debug("Sending command: ap()") - return self.run( - f"ap {ssid} {password}", "Connecting to access point, then rebooting\r\n" - ) + return self.run(f"ap {ssid} {password}", + "Connecting to access point, then rebooting\r\n") def set_wifi_channel(self, channel: int): """Sends command to set the WiFi channel""" @@ -253,9 +254,8 @@ def set_ports(self, status_port: int, video_port: int): "Setting new ports for status and video\r\n", ) if ports == "ok": - logging.info( - "New ports set by client: %s and %s", status_port, video_port - ) + logging.info("New ports set by client: %s and %s", status_port, + video_port) # self.info_port = status_port # self.tello_address = ('192.168.10.1', info_port) # @@ -264,8 +264,7 @@ def set_ports(self, status_port: int, video_port: int): return "ok" logging.warning("tello.set_ports(): Failed to set ports.") logging.debug( - "Failed to set ports due to an error response from the drone." - ) + "Failed to set ports due to an error response from the drone.") return "error" logging.warning("tello.set_ports(): Invalid value.") return "error" @@ -282,11 +281,11 @@ def set_bitrate(self, bitrate: int): """Sends command to set the video stream bitrate""" logging.debug("Sending command: set_bitrate()") if 1 <= bitrate <= 5: - return self.run( - f"setbitrate {bitrate}", f"Setting bitrate to {bitrate} Mbps\r\n" - ) + return self.run(f"setbitrate {bitrate}", + f"Setting bitrate to {bitrate} Mbps\r\n") if bitrate == 0: - return self.run(f"setbitrate {bitrate}", "Setting bitrate to auto\r\n") + return self.run(f"setbitrate {bitrate}", + "Setting bitrate to auto\r\n") logging.warning("tello.set_bitrate(): Invalid value.") return "error" @@ -355,9 +354,8 @@ def up(self, x: int): """Sends command to move up x cm""" logging.debug("Sending command: up()") if 20 <= x <= 500: - return self.run( - f"up {str(x)}", f"Ascending to {str(x)} cm from the ground \r\n" - ) + return self.run(f"up {str(x)}", + f"Ascending to {str(x)} cm from the ground \r\n") logging.warning("tello.up(): Invalid value.") return "error" @@ -365,9 +363,8 @@ def down(self, x: int): """Sends command to move down x cm""" logging.debug("Sending command: down()") if 20 <= x <= 500: - return self.run( - f"down {str(x)}", f"Descending to {str(x)} cm from the ground \r\n" - ) + return self.run(f"down {str(x)}", + f"Descending to {str(x)} cm from the ground \r\n") logging.warning("tello.down(): Invalid value.") return "error" @@ -438,9 +435,8 @@ def flip(self, direction: str): """Sends command to flip in direction specified""" logging.debug("Sending command: flip()") if direction in ("l", "r", "f", "b"): - return self.run( - f"flip {direction}", f"Flipping {direction}, be careful \r\n" - ) + return self.run(f"flip {direction}", + f"Flipping {direction}, be careful \r\n") logging.warning("tello.flip(): Invalid value.") return "error" @@ -449,7 +445,8 @@ def set_speed(self, x: int): """Sends command to set speed to x cm/s""" logging.debug("Sending command: set_speed()") if x >= 1 and x <= 100: - return self.run(f"speed {str(x)}", f"Setting speed to {str(x)} cm/s \r\n") + return self.run(f"speed {str(x)}", + f"Setting speed to {str(x)} cm/s \r\n") logging.warning("tello.set_speed(): Invalid value.") return "error" @@ -536,12 +533,14 @@ def get_rmtt_wifi_version(self): def get_ap(self): """Sends command to get RMTT AP info""" logging.debug("Sending command: get_ap()") - return self.run("ap?", "Obtaining RMTT Access Point SSID and password \r\n") + return self.run("ap?", + "Obtaining RMTT Access Point SSID and password \r\n") def get_rmtt_wifi(self): """Sends command to get RMTT SSID""" logging.debug("Sending command: get_ssid()") - return self.run("ssid?", "Obtaining RMTT WiFi SSID and password (if any) \r\n") + return self.run("ssid?", + "Obtaining RMTT WiFi SSID and password (if any) \r\n") # COMPLEX Commands def go(self, x: int, y: int, z: int, s: int): @@ -558,17 +557,13 @@ def go(self, x: int, y: int, z: int, s: int): logging.warning("tello.go(): Invalid coordinates.") return "error" - def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int): + def curve(self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, + s: int): """Sends command to curve from x1 y1 z1 at speed s to x2 y2 z2""" logging.debug("Sending command: curve()") - if ( - 500 >= x1 >= -500 - and 500 >= x2 >= -500 - and 500 >= y1 >= -500 - and 500 >= y2 >= -500 - and 500 >= z1 >= -500 - and 500 >= z2 >= -500 - ): + if (500 >= x1 >= -500 and 500 >= x2 >= -500 and 500 >= y1 >= -500 + and 500 >= y2 >= -500 and 500 >= z1 >= -500 + and 500 >= z2 >= -500): if 60 >= s >= 10: return self.run( f"curve {str(x1)} {str(y1)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)}", @@ -596,16 +591,16 @@ def go_mission_pad(self, x: int, y: int, z: int, s: int, mid: str): f"go {str(x)} {str(y)} {str(z)} {str(s)} {str(mid)}", f"Going to (x, y, z): {str(x)} {str(y)} {str(z)} at the speed of {str(s)} cm/s\r\n", ) - logging.warning("tello.go_mission_pad(): Invalid mission pad ID.") + logging.warning( + "tello.go_mission_pad(): Invalid mission pad ID.") return "error" logging.warning("tello.go_mission_pad(): Invalid speed.") return "error" logging.warning("tello.go_mission_pad(): Invalid coordinates.") return "error" - def curve_mission_pad( - self, x1: int, x2: int, y1: int, y2: int, z1: int, z2: int, s: int, mid: str - ): + def curve_mission_pad(self, x1: int, x2: int, y1: int, y2: int, z1: int, + z2: int, s: int, mid: str): """Sends command to curve from x y z 1 at speed s to x y z 2 and find Mpad mid""" logging.debug("Sending command: curve_mission_pad()") mid_ok = False @@ -613,21 +608,17 @@ def curve_mission_pad( if id == mid: mid_ok = True break - if ( - 500 >= x1 >= -500 - and 500 >= x2 >= -500 - and 500 >= y1 >= -500 - and 500 >= y2 >= -500 - and 500 >= z1 >= -500 - and 500 >= z2 >= -500 - ): + if (500 >= x1 >= -500 and 500 >= x2 >= -500 and 500 >= y1 >= -500 + and 500 >= y2 >= -500 and 500 >= z1 >= -500 + and 500 >= z2 >= -500): if 60 >= s >= 10: if mid_ok: return self.run( f"curve {str(x1)} {str(x2)} {str(z1)} {str(x2)} {str(y2)} {str(z2)} {str(s)} {str(mid)}", f"Curving from (x, y, z): {x1} {y1} {z1} to {x2} {y2} {z2} at the speed of {str(s)} cm/s\r\n", ) - logging.warning("tello.curve_mission_pad(): Invalid mission pad ID.") + logging.warning( + "tello.curve_mission_pad(): Invalid mission pad ID.") return "error" logging.warning("tello.curve_mission_pad(): Invalid speed.") return "error" @@ -662,20 +653,13 @@ def set_light_pulse(self, r: int, g: int, b: int, p: float or int): logging.warning("tello.set_light_pulse(): Invalid values.") return "led error" - def set_light_flash( - self, r1: int, g1: int, b1: int, r2: int, g2: int, b2: int, f: float or int - ): + def set_light_flash(self, r1: int, g1: int, b1: int, r2: int, g2: int, + b2: int, f: float or int): """Sends command to set the 2 colors of the LED to flash""" logging.debug("Sending command: set_light_flash()") - if ( - 255 >= r1 >= 0 - and 255 >= g1 >= 0 - and 255 >= b1 >= 0 - and 255 >= r2 >= 0 - and 255 >= g2 >= 0 - and 255 >= b2 >= 0 - and 2.5 >= f >= 0.1 - ): + if (255 >= r1 >= 0 and 255 >= g1 >= 0 and 255 >= b1 >= 0 + and 255 >= r2 >= 0 and 255 >= g2 >= 0 and 255 >= b2 >= 0 + and 2.5 >= f >= 0.1): return self.run( f"EXT led bl {str(f)} {str(r1)} {str(g1)} {str(b1)} {str(r2)} {str(g2)} {str(b2)}", f"Setting RMTT light color to (r, g, b): {str(r1)}, {str(g1)}, {str(b1)} and {str(r2)}, {str(g2)}, {str(b2)} with flash of {str(f)} Hz\r\n", @@ -688,7 +672,8 @@ def set_display_pattern(self, pattern: str = "0"): logging.debug("Sending command: set_display_pattern()") for char in pattern: if char not in "rbp0": - logging.warning("tello.set_display_pattern(): Invalid pattern.") + logging.warning( + "tello.set_display_pattern(): Invalid pattern.") return "matrix error" return self.run( f"EXT mled g {str(pattern)}", @@ -703,14 +688,14 @@ def set_display_blank(self): # TO TEST "Turning off the display\r\n", ) - def set_display_string( - self, direction: str, color: str, frame_rate: float or int, string: str - ): + def set_display_string(self, direction: str, color: str, frame_rate: float + or int, string: str): """Sends command to show a string on the display""" logging.debug("Sending command: set_display_string()") for char in direction: if char not in "lrud": - logging.warning("tello.set_display_string(): Invalid direction.") + logging.warning( + "tello.set_display_string(): Invalid direction.") return "matrix error" if color in ("r", "b", "p") and 10 >= frame_rate >= 0.1: return self.run( @@ -720,18 +705,19 @@ def set_display_string( logging.warning("tello.set_display_string(): Invalid values.") return "matrix error" - def set_display_moving_image( - self, direction: str, color: str, frame_rate: float or int, pattern: str - ): + def set_display_moving_image(self, direction: str, color: str, + frame_rate: float or int, pattern: str): """Sends command to show a moving image on the display""" logging.debug("Sending command: set_display_moving_image()") for char in direction: if char not in "lrud": - logging.warning("tello.set_display_moving_image(): Invalid direction.") + logging.warning( + "tello.set_display_moving_image(): Invalid direction.") return "matrix error" for char in pattern: if char not in "rbp0": - logging.warning("tello.set_display_moving_image(): Invalid pattern.") + logging.warning( + "tello.set_display_moving_image(): Invalid pattern.") return "matrix error" if color in ("r", "b", "p") and 10 >= frame_rate >= 0.1: return self.run( @@ -744,11 +730,8 @@ def set_display_moving_image( def set_display_ascii_character(self, character: str, color: str): # TEST """Sends command to display ascii character""" logging.debug("Sending command: set_display_ascii_character()") - if ( - character == "heart" - or character.encode("ascii") - and color in ("r", "b", "p") - ): + if (character == "heart" + or character.encode("ascii") and color in ("r", "b", "p")): return self.run( # TEST f'EXT mled s {str(color)} {str(character.encode("ascii"))}', @@ -772,7 +755,8 @@ def set_display_boot(self, pattern: str): def clear_display_boot(self): """Sends command to clear the display boot pattern""" logging.debug("Sending command: clear_display_boot()") - return self.run("EXT mled sc", "Clearing RMTT boot display pattern\r\n") + return self.run("EXT mled sc", + "Clearing RMTT boot display pattern\r\n") def set_display_brightness(self, brightness: int): """Sends command to set the display brightness""" @@ -788,7 +772,8 @@ def set_display_brightness(self, brightness: int): def get_tof(self): """Sends command to get the distance from the drone to the nearest obstacle in front""" logging.debug("Sending command: get_tof()") - return self.run("EXT tof?", "Getting ToF (read docs for more info)...\r\n") + return self.run("EXT tof?", + "Getting ToF (read docs for more info)...\r\n") def get_esp32_version(self): """Sends command to get the ESP32 version""" diff --git a/tello_sdk/telloLive.py b/tello_sdk/telloLive.py index d7b592c..e0073b7 100644 --- a/tello_sdk/telloLive.py +++ b/tello_sdk/telloLive.py @@ -10,7 +10,6 @@ port = 9000 locaddr = (host, port) - # Print general info for the user print("_________ ____ ____ ") print(" | | | | | |") @@ -26,7 +25,6 @@ print(" Checking network... \r\n") time.sleep(1) - try: process = subprocess.Popen( [ @@ -48,7 +46,8 @@ print( "It seems like you have joined a different network. Please make sure that you have joined the TELLO-XXXXX Wi-Fi." ) - approval = input("Are you sure you want to continue with the script? (y/n)") + approval = input( + "Are you sure you want to continue with the script? (y/n)") if approval == "y": print("\r\n") else: @@ -60,11 +59,9 @@ print("\r\nSeems like there was an error checking the network.") print("Continuing.\r\n") - print(" Making UDP socket... \r\n") time.sleep(1) - # Create a UDP socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -92,7 +89,8 @@ def recv(): break -print("\r\nTo view all available functions, type", "\033[1m" + "help" + "\033[0m") +print("\r\nTo view all available functions, type", + "\033[1m" + "help" + "\033[0m") print("\r\nTo quit the script, type", "\033[1m" + "end" + "\033[0m") print( "\r\n(For emergencies) To immediately quit the script, press", @@ -105,12 +103,10 @@ def recv(): ) print("\r\nTo begin, type", "\033[1m" + "command" + "\033[0m: \r\n") - # recvThread create recvThread = threading.Thread(target=recv) recvThread.start() - # Main loop: what happens repeatedly while True: try: @@ -162,10 +158,14 @@ def recv(): " curve x1 y1 z1 x2 y2 z2 s -- Fly at a curve (make corner from coordinates) at s speed (arc radius must be between 0.5m and 10m)" ) print(" x1, x2 = left, right (-500 to 500)") - print(" y1, y2 = forwards, backwards (-500 to 500)") + print( + " y1, y2 = forwards, backwards (-500 to 500)" + ) print(" z1, z2 = up, down (-500 to 500)") print(" s = cm/s (10 to 60)") - print(" go x y z s mid -- Fly to x y z at speed s of the mission pad") + print( + " go x y z s mid -- Fly to x y z at speed s of the mission pad" + ) print(" x = left, right (-500 to 500)") print(" y = forwards, backwards (-500 to 500)") print(" z = up, down (-500 to 500)") @@ -175,7 +175,9 @@ def recv(): " curve x1 y1 z1 x2 y2 z2 s mid -- Fly at a curve (make corner from coordinates) at s speed (arc radius must be between 0.5m and 10m) of the mission pad" ) print(" x1, x2 = left, right (-500 to 500)") - print(" y1, y2 = forwards, backwards (-500 to 500)") + print( + " y1, y2 = forwards, backwards (-500 to 500)" + ) print(" z1, z2 = up, down (-500 to 500)") print(" s = cm/s (10 to 60)") print( @@ -192,7 +194,9 @@ def recv(): elif msg == "help set": print("\r\nSet commands:") print(" speed x -- Set speed to x (10 to 100 cm/s)") - print(" wifi name pass -- Set Wi-Fi ssid to name and password to pass") + print( + " wifi name pass -- Set Wi-Fi ssid to name and password to pass" + ) print(" mon -- Enable mission pad detection") print(" moff -- Disable mission pad detection") print(