mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-09 22:49:53 +08:00
[parrot] factorize Parrot tools
This commit is contained in:
+315
-442
File diff suppressed because it is too large
Load Diff
+29
-185
@@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2012-2014 The Paparazzi Team
|
||||
# 2015 Freek van Tienen <freek.v.tienen@gmail.com>
|
||||
# 2017 Gautier Hattenberger <gautier.hattenberger@enac.fr>
|
||||
#
|
||||
# This file is part of Paparazzi.
|
||||
#
|
||||
@@ -20,192 +22,34 @@
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import re
|
||||
import argparse
|
||||
import os
|
||||
from time import sleep
|
||||
from parrot_utils import ParrotUtils
|
||||
|
||||
import parrot_utils
|
||||
class Bebop(ParrotUtils):
|
||||
uav_name = 'Bebop'
|
||||
address = '192.168.42.1'
|
||||
version_file = '/version.txt'
|
||||
upload_path = '/data/ftp/'
|
||||
check_version_before_run = True
|
||||
update_time_before_run = True
|
||||
|
||||
def uav_status(self):
|
||||
print('Parrot version:\t\t' + self.check_version())
|
||||
|
||||
def init_extra_parser(self):
|
||||
|
||||
# Parse the extra arguments
|
||||
self.parser.add_argument('--min_version', metavar='MIN', default='3.3.0',
|
||||
help='force minimum version allowed')
|
||||
self.parser.add_argument('--max_version', metavar='MAX', default='4.0.5',
|
||||
help='force maximum version allowed')
|
||||
|
||||
def parse_extra_args(self, args):
|
||||
# nothing here
|
||||
pass
|
||||
|
||||
|
||||
# Read from config.ini TODO
|
||||
def read_from_config(name, config=''):
|
||||
if config == '':
|
||||
config = parrot_utils.execute_command('cat /data/config.ini')
|
||||
search = re.search(name + '[^=]+=[\r\n\t ]([^\r\n\t ]+)', config)
|
||||
if search is None:
|
||||
return ''
|
||||
else:
|
||||
return search.group(1)
|
||||
if __name__ == "__main__":
|
||||
bebop = Bebop()
|
||||
bebop.parse_args()
|
||||
exit(0)
|
||||
|
||||
# Write to config TODO
|
||||
def write_to_config(name, value):
|
||||
if read_from_config(name) == '':
|
||||
parrot_utils.execute_command('echo "' + name + ' = ' + value + '\" >> /data/config.ini')
|
||||
else:
|
||||
parrot_utils.execute_command('sed -i "s/\(' + name + ' *= *\).*/\\1' + value + '/g" /data/config.ini')
|
||||
|
||||
|
||||
def bebop_status():
|
||||
#config_ini = parrot_utils.execute_command(tn, 'cat /data/config.ini')
|
||||
|
||||
print('======================== Bebop Status ========================')
|
||||
print('Version:\t\t' + str(parrot_utils.check_version(tn, '')))
|
||||
# Request the filesystem status
|
||||
print('\n=================== Filesystem Status =======================')
|
||||
print(parrot_utils.check_filesystem(tn))
|
||||
|
||||
|
||||
# Parse the arguments
|
||||
parser = argparse.ArgumentParser(description='Bebop helper tool. Use bebop.py -h for help')
|
||||
parser.add_argument('--host', metavar='HOST', default='192.168.42.1',
|
||||
help='the ip address of bebop')
|
||||
parser.add_argument('--min_version', metavar='MIN', default='3.3.0',
|
||||
help='force minimum version allowed')
|
||||
parser.add_argument('--max_version', metavar='MAX', default='4.0.5',
|
||||
help='force maximum version allowed')
|
||||
subparsers = parser.add_subparsers(title='Command to execute', metavar='command', dest='command')
|
||||
|
||||
# All the subcommands and arguments
|
||||
subparsers.add_parser('status', help='Request the status of the Bebop')
|
||||
subparsers.add_parser('reboot', help='Reboot the Bebop')
|
||||
subparser_upload_and_run = subparsers.add_parser('upload_file_and_run', help='Upload and run software (for instance the Paparazzi autopilot)')
|
||||
subparser_upload_and_run.add_argument('file', help='Filename of an executable')
|
||||
subparser_upload_and_run.add_argument('folder', help='Destination subfolder (raw for Paparazzi autopilot)')
|
||||
subparser_upload = subparsers.add_parser('upload_file', help='Upload a file to the Bebop')
|
||||
subparser_upload.add_argument('file', help='Filename')
|
||||
subparser_upload.add_argument('folder', help='Destination subfolder (base destination folder is /data/ftp)')
|
||||
subparser_download = subparsers.add_parser('download_file', help='Download a file from the Bebop')
|
||||
subparser_download.add_argument('file', help='Filename (with the path on the local machine)')
|
||||
subparser_download.add_argument('folder', help='Remote subfolder (base folder is /data/ftp)')
|
||||
subparser_download_dir = subparsers.add_parser('download_dir', help='Download all files from a folder from the Bebop')
|
||||
subparser_download_dir.add_argument('dest', help='destination folder (on the local machine)')
|
||||
subparser_download_dir.add_argument('folder', help='Remote subfolder (base folder is /data/ftp)')
|
||||
subparser_rm_dir = subparsers.add_parser('rm_dir', help='Remove a directory and all its files from the Bebop')
|
||||
subparser_rm_dir.add_argument('folder', help='Remote subfolder (base folder is /data/ftp)')
|
||||
subparser_insmod = subparsers.add_parser('insmod', help='Upload and insert kernel module')
|
||||
subparser_insmod.add_argument('file', help='Filename of *.ko kernel module')
|
||||
subparser_start = subparsers.add_parser('start', help='Start a program on the Bebop')
|
||||
subparser_start.add_argument('program', help='the program to start')
|
||||
subparser_kill = subparsers.add_parser('kill', help='Kill a program on the Bebop')
|
||||
subparser_kill.add_argument('program', help='the program to kill')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Connect with telnet and ftp
|
||||
tn, ftp = parrot_utils.connect(args.host)
|
||||
|
||||
# Check the Bebop status
|
||||
if args.command == 'status':
|
||||
print("Connected to Bebop at " + args.host)
|
||||
bebop_status()
|
||||
|
||||
# Reboot the drone
|
||||
elif args.command == 'reboot':
|
||||
parrot_utils.reboot(tn)
|
||||
print('The Bebop is rebooting...')
|
||||
|
||||
# Kill a program
|
||||
elif args.command == 'kill':
|
||||
parrot_utils.execute_command(tn, 'killall -9 ' + args.program)
|
||||
print('Program "' + args.program + '" is now killed')
|
||||
|
||||
# Start a program
|
||||
elif args.command == 'start':
|
||||
parrot_utils.execute_command(tn, args.start + ' &')
|
||||
print('Program "' + args.start + '" is now started')
|
||||
|
||||
|
||||
elif args.command == 'insmod':
|
||||
modfile = parrot_utils.split_into_path_and_file(args.file)
|
||||
print('Uploading \'' + modfile[1])
|
||||
parrot_utils.uploadfile(ftp, modfile[1], file(args.file, "rb"))
|
||||
print(parrot_utils.execute_command(tn, "insmod /data/ftp/" + modfile[1]))
|
||||
|
||||
elif args.command == 'upload_file_and_run':
|
||||
# Split filename and path
|
||||
f = parrot_utils.split_into_path_and_file(args.file)
|
||||
|
||||
#check firmware version
|
||||
v = parrot_utils.check_version(tn, '')
|
||||
print("Checking Bebop firmware version... " + str(v) )
|
||||
if ((v < parrot_utils.ParrotVersion(args.min_version)) or (v > parrot_utils.ParrotVersion(args.max_version))):
|
||||
print("Error: please upgrade your Bebop firmware to version between " + args.min_version + " and " + args.max_version + "!")
|
||||
else:
|
||||
print("Kill running " + f[1] + " and make folder " + args.folder)
|
||||
parrot_utils.execute_command(tn,"killall -9 " + f[1])
|
||||
sleep(1)
|
||||
parrot_utils.execute_command(tn, "mkdir -p /data/ftp/" + args.folder)
|
||||
print('Uploading \'' + f[1] + "\' from " + f[0] + " to " + args.folder)
|
||||
parrot_utils.uploadfile(ftp, args.folder + "/" + f[1], file(args.file, "rb"))
|
||||
sleep(0.5)
|
||||
|
||||
from datetime import datetime
|
||||
parrot_utils.execute_command(tn, "date --set '" + datetime.now().strftime('%Y-%m-%d %H:%M:%S') + "'")
|
||||
print("Set date on Bebop to " + datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
|
||||
parrot_utils.execute_command(tn, "chmod 777 /data/ftp/" + args.folder + "/" + f[1])
|
||||
parrot_utils.execute_command(tn, "/data/ftp/" + args.folder + "/" + f[1] + " > /dev/null 2>&1 &")
|
||||
print("#pragma message: Upload and Start of ap.elf to Bebop succesful !")
|
||||
|
||||
|
||||
elif args.command == 'upload_file':
|
||||
# Split filename and path
|
||||
f = parrot_utils.split_into_path_and_file(args.file)
|
||||
|
||||
parrot_utils.execute_command(tn, "mkdir -p /data/ftp/" + args.folder)
|
||||
print('Uploading \'' + f[1] + "\' from " + f[0] + " to /data/ftp/" + args.folder)
|
||||
parrot_utils.uploadfile(ftp, args.folder + "/" + f[1], file(args.file, "rb"))
|
||||
print("#pragma message: Upload of " + f[1] + " to Bebop succesful !")
|
||||
|
||||
elif args.command == 'download_file':
|
||||
# Split filename and path
|
||||
f = parrot_utils.split_into_path_and_file(args.file)
|
||||
# Open file and download
|
||||
try:
|
||||
fd = open(args.file, 'wb')
|
||||
print('Downloading \'' + f[1] + "\' from " + args.folder + " to " + f[0])
|
||||
ftp.retrbinary("RETR " + args.folder + "/" + f[1], fd.write)
|
||||
print("#pragma message: Download of " + f[1] + " from Bebop Succes!")
|
||||
except IOError:
|
||||
print("#pragma message: Fail to open file " + args.file)
|
||||
except:
|
||||
os.remove(args.file)
|
||||
print("#pragma message: Download of " + f[1] + " from Bebop Failed!")
|
||||
else:
|
||||
fd.close()
|
||||
|
||||
elif args.command == 'download_dir':
|
||||
# Split filename and path
|
||||
files = parrot_utils.execute_command(tn, 'find /data/ftp/' + args.folder + ' -name \'*.*\'')
|
||||
# Create dest dir if needed
|
||||
if not os.path.exists(args.dest):
|
||||
os.mkdir(args.dest)
|
||||
# Open file and download
|
||||
for f in files.split():
|
||||
file_name = parrot_utils.split_into_path_and_file(f)
|
||||
file_source = args.folder + '/' + file_name[1]
|
||||
file_dest = args.dest + '/' + file_name[1]
|
||||
try:
|
||||
fd = open(file_dest, 'wb')
|
||||
print('Downloading \'' + f + "\' to " + file_dest)
|
||||
ftp.retrbinary("RETR " + file_source, fd.write)
|
||||
except IOError:
|
||||
print("#pragma message: Fail to open file " + file_dest)
|
||||
except:
|
||||
os.remove(file_dest)
|
||||
print("#pragma message: Download of " + f + " from Bebop Failed!")
|
||||
else:
|
||||
fd.close()
|
||||
print("#pragma message: End download of folder " + args.folder + " from Bebop")
|
||||
|
||||
elif args.command == 'rm_dir':
|
||||
# Split filename and path
|
||||
print("Deleting folder /data/ftp/" + args.folder + " from Bebop")
|
||||
print(parrot_utils.execute_command(tn, 'rm -r /data/ftp/' + args.folder))
|
||||
|
||||
|
||||
|
||||
# Close the telnet and python script
|
||||
parrot_utils.disconnect(tn, ftp)
|
||||
exit(0)
|
||||
|
||||
+304
-66
@@ -1,5 +1,7 @@
|
||||
#
|
||||
# Copyright (C) 2012-2014 The Paparazzi Team
|
||||
# 2015 Freek van Tienen <freek.v.tienen@gmail.com>
|
||||
# 2017 Gautier Hattenberger <gautier.hattenberger@enac.fr>
|
||||
#
|
||||
# This file is part of Paparazzi.
|
||||
#
|
||||
@@ -21,9 +23,13 @@
|
||||
from __future__ import print_function
|
||||
import socket
|
||||
import telnetlib
|
||||
import os
|
||||
import sys
|
||||
from ftplib import FTP
|
||||
from time import sleep
|
||||
import ftplib
|
||||
import argparse
|
||||
import re
|
||||
|
||||
class ParrotVersion(object):
|
||||
def __init__(self):
|
||||
@@ -69,84 +75,316 @@ class ParrotVersion(object):
|
||||
def __ge__(self, other):
|
||||
return self.version() >= other.version()
|
||||
|
||||
class ParrotUtils:
|
||||
|
||||
# Check if IP is valid
|
||||
def is_ip(address):
|
||||
try:
|
||||
socket.inet_aton(address)
|
||||
ip = True
|
||||
except socket.error:
|
||||
ip = False
|
||||
return ip
|
||||
# Programs that could be running on the drone
|
||||
runnable_programs = [
|
||||
('program.elf', 'Parrot native UAV application'),
|
||||
('dragon-prog', 'Parrot native UAV application'),
|
||||
('ap.elf', 'Paparazzi'),
|
||||
('gst-launch', 'GStreamer')
|
||||
]
|
||||
|
||||
# Helper function
|
||||
def split_into_path_and_file(name):
|
||||
if name.count('/') <= 0:
|
||||
return ["./", name]
|
||||
return name.rsplit('/', 1)
|
||||
# Default values
|
||||
version_file = '/update/version.txt'
|
||||
upload_path = '/data/video/'
|
||||
uav_name = 'Parrot UAV'
|
||||
address = '192.168.1.1'
|
||||
prompt = '# '
|
||||
check_version_before_run = False
|
||||
update_time_before_run = False
|
||||
|
||||
# Execute a command
|
||||
def execute_command(tn, command, prompt='#'):
|
||||
tn.write(command + '\n')
|
||||
return tn.read_until(prompt+' ')[len(command) + 2:-4]
|
||||
# Initialize defaults
|
||||
def __init__(self):
|
||||
self.config_content = ''
|
||||
self.init_parser()
|
||||
self.init_extra_parser()
|
||||
|
||||
# Check the version
|
||||
def check_version(tn, directory, prompt='#'):
|
||||
return ParrotVersion(execute_command(tn, 'cat ' + directory + '/version.txt', prompt).strip())
|
||||
# Connect with telnet and ftp, wait until login
|
||||
def connect(self):
|
||||
try:
|
||||
self.tn = telnetlib.Telnet(self.address, timeout=3)
|
||||
self.ftp = FTP(self.address)
|
||||
self.ftp.login()
|
||||
self.tn.read_until(self.prompt)
|
||||
return True
|
||||
except:
|
||||
print('Could not connect to the ' + self.uav_name + ' (address: ' + self.address + ')')
|
||||
print('Check if the ' + self.uav_name + ' is turned on and the computer is connected over wifi or bluetooth.')
|
||||
if self.address == '192.168.42.1':
|
||||
print("If you are using Bebop 1 or 2, don't forget pressing the power button 4 times after the Bebop has booted!")
|
||||
exit(2)
|
||||
|
||||
# Check what currently is running on the drone
|
||||
def check_running(tn, prompt='#'):
|
||||
ps_aux = execute_command(tn, 'ps', prompt)
|
||||
running = ""
|
||||
# Close the telnet and ftp
|
||||
def disconnect(self):
|
||||
self.tn.close()
|
||||
self.ftp.close()
|
||||
|
||||
# Execute a command
|
||||
def execute_command(self, command):
|
||||
self.tn.write(command + '\n')
|
||||
s = self.tn.read_until(self.prompt)
|
||||
if s.endswith('[JS] $ '):
|
||||
s = s[len(command) + 2:-8]
|
||||
elif s.endswith('[RS.edu] $ '):
|
||||
s = s[len(command) + 2:-12]
|
||||
else:
|
||||
s = s[len(command) + 2:-4]
|
||||
return s
|
||||
|
||||
# Upload ftp and catch memory-full error
|
||||
def upload(self, filename, content):
|
||||
try:
|
||||
self.ftp.storbinary("STOR " + filename, content)
|
||||
except ftplib.error_temp:
|
||||
print('FTP UPLOAD ERROR: Uploading the file to the ' + self.uav_name + ' failed!')
|
||||
print('Check if the Filesystem of the ' + self.uav_name + ' isn\'t full:')
|
||||
print(self.check_filesystem())
|
||||
sys.exit()
|
||||
except:
|
||||
print('FTP UPLOAD ERROR: Uploading the file to the ' + self.uav_name + ' failed!')
|
||||
print('FTP uploading failed with the following error: ', sys.exc_info()[0])
|
||||
print('Check if the Filesystem of the ' + self.uav_name + ' isn\'t full:')
|
||||
print(self.check_filesystem())
|
||||
sys.exit()
|
||||
|
||||
# Download a file from the drone
|
||||
def download(self, filename, folder):
|
||||
# Split filename and path
|
||||
f = self.split_into_path_and_file(filename)
|
||||
# Open file and download
|
||||
try:
|
||||
fd = open(filename, 'wb')
|
||||
print('Downloading \'' + f[1] + "\' from " + folder + " to " + f[0])
|
||||
self.ftp.retrbinary("RETR " + folder + "/" + f[1], fd.write)
|
||||
print('#pragma message: Download of "' + f[1] + '" from the ' + self.uav_name + ' success!')
|
||||
except IOError:
|
||||
print('#error: Fail to open local file "' + filename + '"')
|
||||
except:
|
||||
os.remove(filename)
|
||||
print('#error: Download of "' + filename + '" from ' + self.uav_name + ' Failed!')
|
||||
else:
|
||||
fd.close()
|
||||
|
||||
# Download a folder from the drone
|
||||
def download_folder(self, dest, folder):
|
||||
# find files
|
||||
files = self.execute_command('find ' + self.upload_path + folder + ' -name \'*.*\'')
|
||||
# Create dest dir if needed
|
||||
if not os.path.exists(dest):
|
||||
os.mkdir(dest)
|
||||
# Open file and download
|
||||
for f in files.split():
|
||||
file_dest = dest + '/' + file_name[1]
|
||||
self.download(file_dest, folder)
|
||||
print("#pragma message: End download of folder " + args.folder + " from " + self.uav_name)
|
||||
|
||||
|
||||
if 'dragon-prog' in ps_aux:
|
||||
running += ' Native (dragon-prog),'
|
||||
if 'ap.elf' in ps_aux:
|
||||
running += ' Paparazzi (ap.elf),'
|
||||
if 'program.elf' in ps_aux:
|
||||
running += ' Native (program.elf),'
|
||||
if 'gst-launch' in ps_aux:
|
||||
running += ' GStreamer (gst-launch)'
|
||||
return running[1:]
|
||||
# helper function to split file name and path
|
||||
def split_into_path_and_file(self, name):
|
||||
if name.count('/') <= 0:
|
||||
return ["./", name]
|
||||
return name.rsplit('/', 1)
|
||||
|
||||
# Check the filesystem
|
||||
def check_filesystem(tn, prompt='#'):
|
||||
return execute_command(tn, 'df -h', prompt)
|
||||
def is_ip(address):
|
||||
try:
|
||||
socket.inet_aton(address)
|
||||
ip = True
|
||||
except socket.error:
|
||||
ip = False
|
||||
return ip
|
||||
|
||||
# Reboot the drone
|
||||
def reboot(tn, prompt='#'):
|
||||
execute_command(tn, 'reboot', prompt)
|
||||
# Check what currently is running on the drone
|
||||
def check_running(self):
|
||||
ps_aux = self.execute_command('ps')
|
||||
running = ""
|
||||
|
||||
# Upload ftp and catch memory-full error
|
||||
def uploadfile(ftp, filename, content):
|
||||
try:
|
||||
ftp.storbinary("STOR " + filename, content)
|
||||
except ftplib.error_temp:
|
||||
print("FTP UPLOAD ERROR: Uploading FAILED: Probably your drone onboard storage memory is full. Remove old JPG or other data?")
|
||||
sys.exit()
|
||||
except:
|
||||
print("FTP UPLOAD ERROR: Maybe your drone onboard storage memory is full? Remove old JPG or other data?)", sys.exc_info()[0])
|
||||
sys.exit()
|
||||
# Go trough all programings
|
||||
for prog in self.runnable_programs:
|
||||
if prog[0] in ps_aux:
|
||||
running += ' '+prog[1]+' ('+prog[0]+')'
|
||||
|
||||
# Don't print the first space
|
||||
return running[1:]
|
||||
|
||||
# Check the filesystem
|
||||
def check_filesystem(self):
|
||||
return self.execute_command('df -h')
|
||||
|
||||
# Get the version of the drone
|
||||
def check_version(self):
|
||||
if self.version_file is not None:
|
||||
return ParrotVersion(execute_command('cat ' + self.version_file).strip())
|
||||
else:
|
||||
return "Unknown version"
|
||||
|
||||
# Default status
|
||||
def status(self):
|
||||
print('======================== ' + self.uav_name + ' Status ========================')
|
||||
self.uav_status()
|
||||
|
||||
print('\n======================== Filesystem Status ========================')
|
||||
print(self.check_filesystem())
|
||||
|
||||
# Reboot the drone
|
||||
def reboot(self):
|
||||
self.execute_command('reboot')
|
||||
print('The ' + self.uav_name + ' is now rebooting')
|
||||
|
||||
# Kill a running program
|
||||
def kill_program(self, name):
|
||||
self.execute_command('killall -9 ' + name)
|
||||
print('Program "' + name + '" is now killed')
|
||||
|
||||
# Start a new program
|
||||
def start_program(self, name):
|
||||
self.execute_command('chmod 777 ' + name)
|
||||
self.execute_command(name + ' > /dev/null 2>&1 &')
|
||||
print('Program "' + name + '" is now started')
|
||||
|
||||
# Create a new directory
|
||||
def create_directory(self, name):
|
||||
self.execute_command('mkdir -p ' + name)
|
||||
print('Created new directory "' + name + '"')
|
||||
|
||||
# Remove a directory
|
||||
def remove_directory(self, name):
|
||||
self.sexecute_command('rm -r ' + name)
|
||||
print('Removed directory "' + name + '"')
|
||||
|
||||
# Upload a new file
|
||||
def upload_file(self, name, folder=""):
|
||||
f = self.split_into_path_and_file(name)
|
||||
|
||||
# First kill the running program
|
||||
self.kill_program(f[1])
|
||||
sleep(1)
|
||||
|
||||
# Make the upload directory and upload the file
|
||||
self.create_directory(self.upload_path + folder)
|
||||
if len(folder) > 0:
|
||||
self.upload(folder + '/' + f[1], file(name, "rb"))
|
||||
else:
|
||||
self.upload(f[1], file(name, "rb"))
|
||||
sleep(0.5)
|
||||
print('Succesfully uploaded "' + name + '" to folder "' + folder + '"')
|
||||
|
||||
# Upload and run a new program
|
||||
def upload_and_run(self, name, folder, min_ver=None, max_ver=None):
|
||||
if self.check_version_before_run and min_ver is not None and max_ver is not None:
|
||||
v = self.check_version()
|
||||
print("Checking " + self.uav_name + " firmware version... " + str(v) )
|
||||
if ((v < self.ParrotVersion(min_ver)) or (v > self.ParrotVersion(max_ver))):
|
||||
print("Error: please upgrade your " + self.uav_name + " firmware to version between " + min_ver + " and " + max_ver + "!")
|
||||
return
|
||||
|
||||
f = self.split_into_path_and_file(name)
|
||||
|
||||
# Upload the file
|
||||
self.upload_file(name, folder)
|
||||
|
||||
if self.update_time_before_run:
|
||||
from datetime import datetime
|
||||
self.execute_command("date --set '" + datetime.now().strftime('%Y-%m-%d %H:%M:%S') + "'")
|
||||
print("Set date on " + self.uav_name + " to " + datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
|
||||
# Make the file executable and execute it
|
||||
self.start_program(self.upload_path + folder + '/' + f[1])
|
||||
print('#pragma message: Succesfully started "' + f[1] + '" on ' + self.uav_name)
|
||||
|
||||
def insmod(self, modname):
|
||||
f = parrot_utils.split_into_path_and_file(modname)
|
||||
print('Uploading \'' + f[1])
|
||||
self.upload_file(modname)
|
||||
print(self.execute_command("insmod " + self.upload_path + '/' + modfile[1]))
|
||||
|
||||
#####################################################################
|
||||
|
||||
# Main argument parser setup
|
||||
def init_parser(self):
|
||||
self.parser = argparse.ArgumentParser(description=self.uav_name + ' python helper. Use ' + sys.argv[0] + ' -h for help')
|
||||
self.parser.add_argument('--host', metavar='HOST', default=self.address,
|
||||
help='the ip address of ' + self.uav_name)
|
||||
self.subparsers = self.parser.add_subparsers(title='Command to execute', metavar='command', dest='command')
|
||||
|
||||
# Add commands
|
||||
self.subparsers.add_parser('status', help='Request the status of the ' + self.uav_name)
|
||||
self.subparsers.add_parser('reboot', help='Reboot the ' + self.uav_name)
|
||||
|
||||
ss = self.subparsers.add_parser('kill', help='Kill a program on the ' + self.uav_name)
|
||||
ss.add_argument('program', help='The program to kill')
|
||||
|
||||
ss = self.subparsers.add_parser('start', help='Start a program on the ' + self.uav_name)
|
||||
ss.add_argument('program', help='The program to start (base folder is the ftp folder)')
|
||||
|
||||
ss = self.subparsers.add_parser('upload', help='Upload a file to the ' + self.uav_name)
|
||||
ss.add_argument('file', help='Filename')
|
||||
ss.add_argument('folder', help='Destination subfolder (base folder is the ftp folder)')
|
||||
|
||||
ss = self.subparsers.add_parser('download', help='Download a file from the ' + self.uav_name)
|
||||
ss.add_argument('file', help='Remote filename (could include folder)')
|
||||
ss.add_argument('save_file', help='Destination file on local computer')
|
||||
|
||||
ss = self.subparsers.add_parser('download_dir', help='Download all files from a folder from the ' + self.uav_name)
|
||||
ss.add_argument('dest', help='destination folder (on the local machine)')
|
||||
ss.add_argument('folder', help='Remote subfolder (base folder is the ftp folder)')
|
||||
|
||||
ss = self.subparsers.add_parser('upload_file_and_run', help='Upload and run software (for instance the Paparazzi autopilot)')
|
||||
ss.add_argument('file', help='Filename of an executable')
|
||||
ss.add_argument('folder', help='Remote destination folder (base folder is the ftp folder)')
|
||||
|
||||
ss = self.subparsers.add_parser('mkdir', help='Make a new directory on the ' + self.uav_name)
|
||||
ss.add_argument('folder', help='Remote subfolder (base folder is the ftp folder)')
|
||||
|
||||
ss = self.subparsers.add_parser('rmdir', help='Remove a directory and all its files from the ' + self.uav_name)
|
||||
ss.add_argument('folder', help='Remote subfolder (base folder is the ftp folder)')
|
||||
|
||||
ss = self.subparsers.add_parser('insmod', help='Upload and insert kernel module')
|
||||
ss.add_argument('file', help='Filename of *.ko kernel module')
|
||||
|
||||
|
||||
# Connect with telnet and ftp, wait until login
|
||||
def connect(host, prompt='#'):
|
||||
try:
|
||||
tn = telnetlib.Telnet(host, timeout=3)
|
||||
ftp = FTP(host)
|
||||
ftp.login()
|
||||
tn.read_until(prompt+' ')
|
||||
return tn, ftp
|
||||
except:
|
||||
print('Could not connect to Parrot UAV (host: ' + host + ')')
|
||||
if host == '192.168.42.1':
|
||||
print("Check whether your WiFi is connected and don't forget pressing the power button 4 times after the Bebop has booted!")
|
||||
exit(2)
|
||||
# Main function to parse arguments
|
||||
def parse_args(self):
|
||||
args = self.parser.parse_args()
|
||||
|
||||
# First connect to the drone
|
||||
self.address = args.host
|
||||
if self.connect() == False:
|
||||
return False
|
||||
|
||||
# Parse the command line arguments
|
||||
if args.command == 'status':
|
||||
self.status()
|
||||
elif args.command == 'reboot':
|
||||
self.reboot()
|
||||
elif args.command == 'kill':
|
||||
self.kill_program(args.program)
|
||||
elif args.command == 'start':
|
||||
self.start_program(self.upload_path + args.program)
|
||||
elif args.command == 'upload':
|
||||
self.upload_file(args.file, args.folder)
|
||||
elif args.command == 'download':
|
||||
self.download(args.file, args.save_file)
|
||||
elif args.command == 'upload_file_and_run':
|
||||
if hasattr(args, 'min_version') and hasattr(args, 'max_version'):
|
||||
self.upload_and_run(args.file, args.folder, args.min_version, args.max_version)
|
||||
else:
|
||||
self.upload_and_run(args.file, args.folder)
|
||||
elif args.command == 'mkdir':
|
||||
self.create_directory(self.upload_path + args.folder)
|
||||
elif args.command == 'rmdir':
|
||||
self.remove_directory(self.upload_path + args.folder)
|
||||
elif args.command == 'insmod':
|
||||
self.insmod(args.file)
|
||||
else:
|
||||
if self.parse_extra_args(args) == False:
|
||||
self.disconnect()
|
||||
return False
|
||||
|
||||
# Disconnect
|
||||
self.disconnect()
|
||||
return True
|
||||
|
||||
|
||||
# Close the telnet and ftp
|
||||
def disconnect(tn, ftp):
|
||||
tn.close()
|
||||
ftp.close()
|
||||
|
||||
|
||||
|
||||
+21
-171
@@ -20,179 +20,29 @@
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import re
|
||||
import argparse
|
||||
import os
|
||||
from time import sleep
|
||||
from parrot_utils import ParrotUtils
|
||||
|
||||
import parrot_utils
|
||||
class Swing(ParrotUtils):
|
||||
uav_name = 'Swing'
|
||||
address = '192.168.4.1'
|
||||
version_file = None
|
||||
upload_path = '/data/edu/'
|
||||
prompt = '$ '
|
||||
|
||||
PROMPT = '$'
|
||||
FTP_ROOT = '/data/edu/'
|
||||
def uav_status(self):
|
||||
print('Parrot version:\t\t' + self.check_version())
|
||||
|
||||
def init_extra_parser(self):
|
||||
# nothing here
|
||||
pass
|
||||
|
||||
def parse_extra_args(self, args):
|
||||
# nothing here
|
||||
pass
|
||||
|
||||
|
||||
# Read from config.ini TODO
|
||||
def read_from_config(name, config=''):
|
||||
if config == '':
|
||||
config = parrot_utils.execute_command('cat /data/config.ini', prompt=PROMPT)
|
||||
search = re.search(name + '[^=]+=[\r\n\t ]([^\r\n\t ]+)', config)
|
||||
if search is None:
|
||||
return ''
|
||||
else:
|
||||
return search.group(1)
|
||||
if __name__ == "__main__":
|
||||
swing = Swing()
|
||||
swing.parse_args()
|
||||
exit(0)
|
||||
|
||||
# Write to config TODO
|
||||
def write_to_config(name, value):
|
||||
if read_from_config(name) == '':
|
||||
parrot_utils.execute_command('echo "' + name + ' = ' + value + '\" >> /data/config.ini', prompt=PROMPT)
|
||||
else:
|
||||
parrot_utils.execute_command('sed -i "s/\(' + name + ' *= *\).*/\\1' + value + '/g" /data/config.ini', prompt=PROMPT)
|
||||
|
||||
|
||||
def swing_status():
|
||||
#config_ini = parrot_utils.execute_command(tn, 'cat /data/config.ini', prompt=PROMPT)
|
||||
|
||||
#print('==================== Swing Status ====================')
|
||||
#print('Version:\t\t' + str(parrot_utils.check_version(tn, '', prompt=PROMPT)))
|
||||
# Request the filesystem status
|
||||
print('\n=================== Filesystem Status =======================')
|
||||
print(parrot_utils.check_filesystem(tn, prompt=PROMPT))
|
||||
|
||||
|
||||
# Parse the arguments
|
||||
parser = argparse.ArgumentParser(description='Swing python helper. Use swing.py -h for help')
|
||||
parser.add_argument('--host', metavar='HOST', default='192.168.4.1',
|
||||
help='the ip address of Swing')
|
||||
subparsers = parser.add_subparsers(title='Command to execute', metavar='command', dest='command')
|
||||
|
||||
# All the subcommands and arguments
|
||||
subparsers.add_parser('status', help='Request the status of the Swing')
|
||||
subparsers.add_parser('reboot', help='Reboot the Swing')
|
||||
subparser_upload_and_run = subparsers.add_parser('upload_file_and_run', help='Upload and run software (for instance the Paparazzi autopilot)')
|
||||
subparser_upload_and_run.add_argument('file', help='Filename of an executable')
|
||||
subparser_upload_and_run.add_argument('folder', help='Destination subfolder (raw or sdk for Paparazzi autopilot)')
|
||||
subparser_upload = subparsers.add_parser('upload_file', help='Upload a file to the Swing')
|
||||
subparser_upload.add_argument('file', help='Filename')
|
||||
subparser_upload.add_argument('folder', help='Destination subfolder (base destination folder is '+FTP_ROOT+')')
|
||||
subparser_download = subparsers.add_parser('download_file', help='Download a file from the Swing')
|
||||
subparser_download.add_argument('file', help='Filename (with the path on the local machine)')
|
||||
subparser_download.add_argument('folder', help='Remote subfolder (base folder is '+FTP_ROOT+')')
|
||||
subparser_download_dir = subparsers.add_parser('download_dir', help='Download all files from a folder from the Swing')
|
||||
subparser_download_dir.add_argument('dest', help='destination folder (on the local machine)')
|
||||
subparser_download_dir.add_argument('folder', help='Remote subfolder (base folder is '+FTP_ROOT+')')
|
||||
subparser_rm_dir = subparsers.add_parser('rm_dir', help='Remove a directory and all its files from the Swing')
|
||||
subparser_rm_dir.add_argument('folder', help='Remote subfolder (base folder is '+FTP_ROOT+')')
|
||||
subparser_insmod = subparsers.add_parser('insmod', help='Upload and insert kernel module')
|
||||
subparser_insmod.add_argument('file', help='Filename of *.ko kernel module')
|
||||
subparser_start = subparsers.add_parser('start', help='Start a program on the Swing')
|
||||
subparser_start.add_argument('program', help='the program to start')
|
||||
subparser_kill = subparsers.add_parser('kill', help='Kill a program on the Swing')
|
||||
subparser_kill.add_argument('program', help='the program to kill')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Connect with telnet and ftp
|
||||
tn, ftp = parrot_utils.connect(args.host, prompt=PROMPT)
|
||||
|
||||
# Check the Swing status
|
||||
if args.command == 'status':
|
||||
print("Connected to Swing at " + args.host)
|
||||
swing_status()
|
||||
|
||||
# Reboot the drone
|
||||
elif args.command == 'reboot':
|
||||
parrot_utils.reboot(tn, prompt=PROMPT)
|
||||
print('The Swing is rebooting...')
|
||||
|
||||
# Kill a program
|
||||
elif args.command == 'kill':
|
||||
parrot_utils.execute_command(tn, 'killall -9 ' + args.program, prompt=PROMPT)
|
||||
print('Program "' + args.program + '" is now killed')
|
||||
|
||||
# Start a program
|
||||
elif args.command == 'start':
|
||||
parrot_utils.execute_command(tn, args.start + ' &', prompt=PROMPT)
|
||||
print('Program "' + args.start + '" is now started')
|
||||
|
||||
|
||||
elif args.command == 'insmod':
|
||||
modfile = parrot_utils.split_into_path_and_file(args.file)
|
||||
print('Uploading \'' + modfile[1])
|
||||
parrot_utils.uploadfile(ftp, modfile[1], file(args.file, "rb"))
|
||||
print(parrot_utils.execute_command(tn, "insmod "+ FTP_ROOT + modfile[1], prompt=PROMPT))
|
||||
|
||||
elif args.command == 'upload_file_and_run':
|
||||
# Split filename and path
|
||||
f = parrot_utils.split_into_path_and_file(args.file)
|
||||
|
||||
print("Kill running " + f[1] + " and make folder " + args.folder)
|
||||
parrot_utils.execute_command(tn,"killall -9 " + f[1], prompt=PROMPT)
|
||||
sleep(1)
|
||||
parrot_utils.execute_command(tn, "mkdir -p " + FTP_ROOT + args.folder, prompt=PROMPT)
|
||||
print('Uploading \'' + f[1] + "\' from " + f[0] + " to " + args.folder)
|
||||
parrot_utils.uploadfile(ftp, args.folder + "/" + f[1], file(args.file, "rb"))
|
||||
sleep(0.5)
|
||||
parrot_utils.execute_command(tn, "chmod 777 " + FTP_ROOT + args.folder + "/" + f[1], prompt=PROMPT)
|
||||
parrot_utils.execute_command(tn, FTP_ROOT + args.folder + "/" + f[1] + " > /dev/null 2>&1 &", prompt=PROMPT)
|
||||
print("#pragma message: Upload and Start of ap.elf to Swing Succes!")
|
||||
|
||||
elif args.command == 'upload_file':
|
||||
# Split filename and path
|
||||
f = parrot_utils.split_into_path_and_file(args.file)
|
||||
|
||||
parrot_utils.execute_command(tn, "mkdir -p " + FTP_ROOT + args.folder, prompt=PROMPT)
|
||||
print('Uploading \'' + f[1] + "\' from " + f[0] + " to " + FTP_ROOT + args.folder)
|
||||
parrot_utils.uploadfile(ftp, args.folder + "/" + f[1], file(args.file, "rb"))
|
||||
print("#pragma message: Upload of " + f[1] + " to Swing Succes!")
|
||||
|
||||
elif args.command == 'download_file':
|
||||
# Split filename and path
|
||||
f = parrot_utils.split_into_path_and_file(args.file)
|
||||
# Open file and download
|
||||
try:
|
||||
fd = open(args.file, 'wb')
|
||||
print('Downloading \'' + f[1] + "\' from " + args.folder + " to " + f[0])
|
||||
ftp.retrbinary("RETR " + args.folder + "/" + f[1], fd.write)
|
||||
print("#pragma message: Download of " + f[1] + " from Swing Succes!")
|
||||
except IOError:
|
||||
print("#pragma message: Fail to open file " + args.file)
|
||||
except:
|
||||
os.remove(args.file)
|
||||
print("#pragma message: Download of " + f[1] + " from Swing Failed!")
|
||||
else:
|
||||
fd.close()
|
||||
|
||||
elif args.command == 'download_dir':
|
||||
# Split filename and path
|
||||
files = parrot_utils.execute_command(tn, 'find ' + FTP_ROOT + args.folder + ' -name \'*.*\'', prompt=PROMPT)
|
||||
# Create dest dir if needed
|
||||
if not os.path.exists(args.dest):
|
||||
os.mkdir(args.dest)
|
||||
# Open file and download
|
||||
for f in files.split():
|
||||
file_name = parrot_utils.split_into_path_and_file(f)
|
||||
file_source = args.folder + '/' + file_name[1]
|
||||
file_dest = args.dest + '/' + file_name[1]
|
||||
try:
|
||||
fd = open(file_dest, 'wb')
|
||||
print('Downloading \'' + f + "\' to " + file_dest)
|
||||
ftp.retrbinary("RETR " + file_source, fd.write)
|
||||
except IOError:
|
||||
print("#pragma message: Fail to open file " + file_dest)
|
||||
except:
|
||||
os.remove(file_dest)
|
||||
print("#pragma message: Download of " + f + " from Swing Failed!")
|
||||
else:
|
||||
fd.close()
|
||||
print("#pragma message: End download of folder " + args.folder + " from Swing")
|
||||
|
||||
elif args.command == 'rm_dir':
|
||||
# Split filename and path
|
||||
print("Deleting folder " + FTP_ROOT + args.folder + " from Swing")
|
||||
print(parrot_utils.execute_command(tn, 'rm -r ' + FTP_ROOT + args.folder, prompt=PROMPT))
|
||||
|
||||
|
||||
|
||||
# Close the telnet and python script
|
||||
parrot_utils.disconnect(tn, ftp)
|
||||
exit(0)
|
||||
|
||||
Reference in New Issue
Block a user