diff --git a/sw/tools/parrot/ardrone2.py b/sw/tools/parrot/ardrone2.py index ecc0d22b53..2c091b5ff3 100755 --- a/sw/tools/parrot/ardrone2.py +++ b/sw/tools/parrot/ardrone2.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # # Copyright (C) 2012-2014 The Paparazzi Team +# 2015 Freek van Tienen +# 2017 Gautier Hattenberger # # This file is part of Paparazzi. # @@ -20,456 +22,327 @@ # from __future__ import print_function +from parrot_utils import ParrotUtils import re import argparse -import os from time import sleep -import parrot_utils +class Ardrone2(ParrotUtils): + uav_name = 'Ardrone 2' + config_file = '/data/config.ini' + version_file = '/firmware/version.txt' -# Read from config.ini -def read_from_config(name, config=''): - if config == '': - config = parrot_utils.execute_command(tn, '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) + # Read from config.ini + def read_from_config(self, name): + # Only read file once + if self.config_content == '': + self.config_content = self.execute_command('cat ' + self.config_file) -# Write to config -def write_to_config(name, value): - if read_from_config(name) == '': - parrot_utils.execute_command(tn, 'echo "' + name + ' = ' + value + '\" >> /data/config.ini') - else: - parrot_utils.execute_command(tn, 'sed -i "s/\(' + name + ' *= *\).*/\\1' + value + '/g" /data/config.ini') - -# Check if vision framework is installed -def check_vision_installed(): - du_opt = parrot_utils.execute_command(tn,'du -d 2 /data/video/opt') - return '/data/video/opt/arm/gst' in du_opt or '/data/video/opt/arm/lib' in du_opt or '/data/video/opt/arm/tidsp-binaries-23.i3.8' in du_opt - -# Check if the vision framework is running -def check_vision_running(): - du_opt = parrot_utils.execute_command(tn,'du -d 2 /opt') - return '/opt/arm/gst' in du_opt and '/opt/arm/lib' in du_opt and '/opt/arm/tidsp-binaries-23.i3.8' in du_opt - -# Check if autoboot is installed -def check_autoboot(): - check_update = parrot_utils.execute_command(tn,'grep "START_PAPARAZZI" /bin/check_update.sh') - wifi_setup = parrot_utils.execute_command(tn,'grep "BASE_ADRESS" /bin/wifi_setup.sh') - if "START_PAPARAZZI" in check_update and "BASE_ADRESS" in wifi_setup: - return True - else: - return False - -# Check if custom wifi_setup script is installed -def check_wifi_setup(): - check_wifi = parrot_utils.execute_command(tn,'grep "static_ip_address_base" /bin/wifi_setup.sh') - if "static_ip_address_base" in check_wifi: - return True - else: - return False - -# Install the vision framework -def ardrone2_install_vision(): - print('Uploading GST') - parrot_utils.uploadfile(ftp, "arm_light.tgz", file("bin/arm_light.tgz", "rb")) - print(parrot_utils.execute_command(tn,"cd /data/video && tar -xzf arm_light.tgz")) - print(parrot_utils.execute_command(tn,"rm -rf /data/video/arm_light.tgz")) - print('Now Starting Vision') - ardrone2_start_vision() - -# Remove the vision framework -def ardrone2_remove_vision(): - parrot_utils.execute_command(tn,"rm -rf /opt/arm") - parrot_utils.execute_command(tn,"rm -rf /lib/dsp") - parrot_utils.execute_command(tn,"rm -rf /data/video/opt") - -# Start the vision framework -def ardrone2_start_vision(): - # Mount the directories - parrot_utils.execute_command(tn,"mkdir -p /opt/arm") - parrot_utils.execute_command(tn,"mkdir -p /lib/dsp") - parrot_utils.execute_command(tn,"mount --bind /data/video/opt/arm /opt/arm") - parrot_utils.execute_command(tn,"mount --bind /data/video/opt/arm/lib/dsp /lib/dsp") - # Start The DSP programs - parrot_utils.execute_command(tn,"kill -9 `pidof program.elf`") - parrot_utils.execute_command(tn,"kill -9 `pidof gst-launch-0.10`") - parrot_utils.execute_command(tn,"export PATH=/opt/arm/gst/bin:$PATH") - parrot_utils.execute_command(tn,"export DSP_PATH=/opt/arm/tidsp-binaries-23.i3.8/") - parrot_utils.execute_command(tn,"/bin/dspbridge/cexec.out -T /opt/arm/tidsp-binaries-23.i3.8/baseimage.dof -v") - parrot_utils.execute_command(tn,"/bin/dspbridge/dynreg.out -r /opt/arm/tidsp-binaries-23.i3.8/m4venc_sn.dll64P -v") - # Show result - parrot_utils.execute_command(tn,"ls -altr /opt/arm/gst/bin") - -# Install autoboot script -def ardrone2_install_autoboot(): - print('Uploading autoboot script') - parrot_utils.uploadfile(ftp, "check_update.sh", file("ardrone2/check_update.sh", "rb")) - print(parrot_utils.execute_command(tn,"mv /data/video/check_update.sh /bin/check_update.sh")) - print(parrot_utils.execute_command(tn,"chmod 777 /bin/check_update.sh")) - -# Install network script -def ardrone2_install_network_script(): - print('Uploading Wifi script') - parrot_utils.uploadfile(ftp, "wifi_setup.sh", file("ardrone2/wifi_setup.sh", "rb")) - print(parrot_utils.execute_command(tn,"mv /data/video/wifi_setup.sh /bin/wifi_setup.sh")) - print(parrot_utils.execute_command(tn,"chmod 777 /bin/wifi_setup.sh")) - -# Install olsr deamon -def ardrone2_install_olsrd(): - print('Uploading olsr deamon') - parrot_utils.uploadfile(ftp, "olsrd", file("ardrone2/olsrd", "rb")) - parrot_utils.uploadfile(ftp, "olsrd.conf", file("ardrone2/olsrd.conf", "rb")) - print(parrot_utils.execute_command(tn,"mv /data/video/olsrd /bin/olsrd")) - print(parrot_utils.execute_command(tn,"chmod 777 /bin/olsrd")) - print(parrot_utils.execute_command(tn,"mkdir -p /etc/olsrd")) - print(parrot_utils.execute_command(tn,"mv /data/video/olsrd.conf /etc/olsrd")) - print(parrot_utils.execute_command(tn,"rm -f /var/run && ln -s /tmp /var/run")) # olsrd needs /var/run folder, symlinked to /tmp - -# Set network SSID -def ardrone2_set_ssid(name): - write_to_config('ssid_single_player', name) - print('The network ID (SSID) of the ARDrone 2 is changed to ' + name) - -# Set IP address -def ardrone2_set_ip_address(address): - splitted_ip = address.split(".") - write_to_config('static_ip_address_base', splitted_ip[0] + '.' + splitted_ip[1] + '.' + splitted_ip[2] + '.') - write_to_config('static_ip_address_probe', splitted_ip[3]) - print('The IP Address of the ARDrone 2 is changed to ' + address) - -# Set wifi mode (0: master, 1: ad-hoc, 2: managed, *: master) -def ardrone2_set_wifi_mode(mode): - modes = { 'master' : '0', 'ad-hoc' : '1', 'managed' : '2', 'ad-hoc-olsr' : '3' } - try: - val = modes[mode] - except: - print('Unexpected wifi mode, setting to master (default)') - val = modes['master'] - write_to_config('wifi_mode', val) - print('The Wifi mode of the ARDrone2 is changed to ' + mode + ' (' + val + ')') - -# Set network channel -def ardrone2_set_wifi_channel(chan): - write_to_config('wifi_channel', chan) - print('The network channel of the ARDrone 2 is changed to ' + chan) - -def ardrone2_status(): - config_ini = parrot_utils.execute_command(tn,'cat /data/config.ini') - - print('======================== ARDrone 2 Status ========================') - print('Version:\t\t' + str(parrot_utils.check_version(tn, '/firmware'))) - print('Host:\t\t\t' + args.host + ' (' + read_from_config('static_ip_address_base', config_ini) + - read_from_config('static_ip_address_probe', config_ini) + ' after boot)') - - print('Serial number:\t\t' + read_from_config('drone_serial', config_ini)) - print('Network id:\t\t' + read_from_config('ssid_single_player', config_ini)) - print('Motor software:\t\t' + - read_from_config('motor1_soft', config_ini) + '\t' + read_from_config('motor2_soft', config_ini) + '\t' + - read_from_config('motor3_soft', config_ini) + '\t' + read_from_config('motor4_soft', config_ini)) - print('Motor hardware:\t\t' + - read_from_config('motor1_hard', config_ini) + '\t' + read_from_config('motor2_hard', config_ini) + '\t' + - read_from_config('motor3_hard', config_ini) + '\t' + read_from_config('motor4_hard', config_ini)) - - sleep(2.0) #Wait running process reporting back lag - print('Currently running:\t' + parrot_utils.check_running(tn)) - autorun = {'': 'Native', '0': 'Native', '1': 'Paparazzi'} - if check_autoboot(): - print('Autorun at start:\tInstalled booting ' + autorun[read_from_config('start_paparazzi', config_ini)]) - else: - print('Autorun at start:\tNot installed') - - # Check if the vision framework is installed and running - vision_framework = "" - if check_vision_installed(): - vision_framework += "Installed" - if check_vision_running(): - vision_framework += " and running" - print('Vision framework:\t' + vision_framework) - - # Request the filesystem status - print('\n======================== Filesystem Status ========================') - print(parrot_utils.check_filesystem(tn)) - - -# Parse the arguments -parser = argparse.ArgumentParser(description='ARDrone 2 python helper. Use ardrone2.py -h for help') -parser.add_argument('--host', metavar='HOST', default='192.168.1.1', - help='the ip address of ardrone2') -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 ARDrone 2') -subparsers.add_parser('reboot', help='Reboot the ARDrone 2') -subparsers.add_parser('installvision', help='Install the vision framework') -subparser_upload_gst = subparsers.add_parser('upload_gst_module', - help='Upload, configure and move a gstreamer0.10 module libXXX.so') -subparser_upload_gst.add_argument('file', help='Filename of *.so module') -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 ARDrone 2') -subparser_upload.add_argument('file', help='Filename') -subparser_upload.add_argument('folder', help='Destination subfolder (base destination folder is /data/video)') -subparser_download = subparsers.add_parser('download_file', help='Download a file from the ARDrone 2') -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/video)') -subparser_download_dir = subparsers.add_parser('download_dir', help='Download all files from a folder from the ARDrone 2') -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/video)') -subparser_rm_dir = subparsers.add_parser('rm_dir', help='Remove a directory and all its files from the ARDrone 2') -subparser_rm_dir.add_argument('folder', help='Remote subfolder (base folder is /data/video)') -subparser_insmod = subparsers.add_parser('insmod', help='Upload and insert kernel module') -subparser_insmod.add_argument('file', help='Filename of *.ko kernel module') -subparsers.add_parser('startvision', help='Start the vision framework') -subparser_start = subparsers.add_parser('start', help='Start a program on the ARDrone 2') -subparser_start.add_argument('program', help='the program to start') -subparser_kill = subparsers.add_parser('kill', help='Kill a program on the ARDrone 2') -subparser_kill.add_argument('program', help='the program to kill') -subparser_networkid = subparsers.add_parser('networkid', help='Set the network ID(SSID) of the ARDrone 2') -subparser_networkid.add_argument('name', help='the new network ID(SSID)') -subparser_ipaddress = subparsers.add_parser('ipaddress', help='Set the IP address of the ARDrone 2') -subparser_ipaddress.add_argument('address', help='the new IP address') -subparser_wifimode = subparsers.add_parser('wifimode', help='Set the Wifi mode the ARDrone 2') -subparser_wifimode.add_argument('mode', help='the new Wifi mode', choices=['master', 'ad-hoc', 'managed', 'ad-hoc-olsr']) -subparser_configure_network = subparsers.add_parser('configure_network', help='Configure the network on the ARDrone 2') -subparser_configure_network.add_argument('name', help='the new network ID(SSID)') -subparser_configure_network.add_argument('address', help='the new IP address') -subparser_configure_network.add_argument('mode', help='the new Wifi mode', choices=['master', 'ad-hoc', 'managed', 'ad-hoc-olsr']) -subparser_configure_network.add_argument('--channel', help='the wifi channel (auto or 1 to 11)', default='auto') -subparser_install_autostart = subparsers.add_parser('install_autostart', help='Install custom autostart script and set what to start on boot for the ARDrone 2') -subparser_install_autostart.add_argument('type', choices=['native', 'paparazzi'], - help='what to start on boot') -subparser_autostart = subparsers.add_parser('autostart', help='Set what to start on boot for the ARDrone 2') -subparser_autostart.add_argument('type', choices=['native', 'paparazzi'], - help='what to start on boot') - -args = parser.parse_args() - -# Connect with telnet and ftp -tn, ftp = parrot_utils.connect(args.host) - -# Check the ARDrone 2 status -if args.command == 'status': - ardrone2_status() - -# Reboot the drone -elif args.command == 'reboot': - parrot_utils.reboot(tn) - print('The ARDrone 2 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') - -# Change the network ID -elif args.command == 'networkid': - ardrone2_set_ssid(args.name) - - if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': - parrot_utils.reboot(tn) - -# Change the IP address -elif args.command == 'ipaddress': - ardrone2_set_ip_address(args.address) - - if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': - parrot_utils.reboot(tn) - -# Change the wifi mode -elif args.command == 'wifimode': - ardrone2_set_wifi_mode(args.mode) - - if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': - parrot_utils.reboot(tn) - -# Install and configure network -elif args.command == 'configure_network': - config_ini = parrot_utils.execute_command(tn,'cat /data/config.ini') - print('=== Current network setup ===') - print('Network id:\t' + read_from_config('ssid_single_player', config_ini)) - print('Host:\t\t' + args.host + ' (' + read_from_config('static_ip_address_base', config_ini) + - read_from_config('static_ip_address_probe', config_ini) + ' after boot)') - print('Mode:\t\t' + read_from_config('wifi_mode', config_ini)) - print('Channel:\t' + read_from_config('wifi_channel', config_ini)) - print('=============================') - if check_wifi_setup(): - print('Custom Wifi script already installed') - if raw_input("Shall I reinstall the Wifi script (y/N) ").lower() == 'y': - ardrone2_install_network_script() - else: - if raw_input("Shall I install custom Wifi script (recommanded) (y/N) ").lower() == 'y': - ardrone2_install_network_script() - if raw_input("Shall I install olsrd (ad-hoc wireless mesh routing deamon) (y/N) ").lower() == 'y': - ardrone2_install_olsrd() - ardrone2_set_ssid(args.name) - ardrone2_set_ip_address(args.address) - ardrone2_set_wifi_mode(args.mode) - ardrone2_set_wifi_channel(args.channel) - config_ini = parrot_utils.execute_command(tn,'cat /data/config.ini') - print('== New network setup after boot ==') - print('Network id:\t' + read_from_config('ssid_single_player', config_ini)) - print('Host:\t\t' + read_from_config('static_ip_address_base', config_ini) + - read_from_config('static_ip_address_probe', config_ini)) - print('Mode:\t\t' + read_from_config('wifi_mode', config_ini)) - print('Channel:\t' + read_from_config('wifi_channel', config_ini)) - print('==================================') - - if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': - parrot_utils.reboot(tn) - -# Install and configure autostart -elif args.command == 'install_autostart': - if check_autoboot(): - print('Custom autostart script already installed') - if raw_input("Shall I reinstall the autostart script (y/N) ").lower() == 'y': - ardrone2_install_autoboot() - else: - ardrone2_install_autoboot() - autorun = {'native': '0', 'paparazzi': '1'} - write_to_config('start_paparazzi', autorun[args.type]) - print('The autostart on boot is changed to ' + args.type) - - if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': - parrot_utils.reboot(tn) - -# Change the autostart -elif args.command == 'autostart': - autorun = {'native': '0', 'paparazzi': '1'} - write_to_config('start_paparazzi', autorun[args.type]) - print('The autostart on boot is changed to ' + args.type) - -# Install Vision framework -elif args.command == 'installvision': - if check_vision_installed(): - print('Vision framework already installed') - if raw_input("Shall I reinstall the vision framework? (y/N) ").lower() == 'y': - ardrone2_remove_vision() - ardrone2_install_vision() - - ardrone2_install_vision() - print('Vision framework installed') - -# Start Vision framework -elif args.command == 'startvision': - if check_vision_running(): - print('Vision framework already started') - else: - if not check_vision_installed(): - print('No vision framework installed') - if raw_input("Shall I install the vision framework? (y/N) ").lower() == 'y': - ardrone2_install_vision() - - if check_vision_installed(): - ardrone2_start_vision() - print('Vision framework started') - -elif args.command == 'upload_gst_module': - print('Uploading ...' + args.file) - parrot_utils.uploadfile(ftp, args.file, file(args.file, "rb")) - parrot_utils.execute_command(tn,"chmod 777 /data/video/" + args.file) - parrot_utils.execute_command(tn,"mv /data/video/" + args.file + " /data/video/opt/arm/gst/lib/gstreamer-0.10") - if check_vision_running(): - print('Info: Vision framework already started') - else: - if not check_vision_installed(): - print('Warning: No vision framework installed') - if raw_input("Warning: Shall I install the vision framework? (y/N) ").lower() == 'y': - ardrone2_install_vision() - - if check_vision_installed(): - ardrone2_start_vision() - print('#pragma message: Vision framework started') - print('#pragma message: Vision Plugin Uploaded and DSP 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/video/" + modfile[1])) - -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] + ' &') - sleep(1) - parrot_utils.execute_command(tn, "mkdir -p /data/video/" + args.folder) - print('Uploading \'' + f[1] + "\' from " + f[0] + " to " + args.folder) - print("#pragma message: Please wait, uploading can take some time...") - parrot_utils.uploadfile(ftp, args.folder + "/" + f[1], file(args.file, "rb")) - sleep(0.5) - parrot_utils.execute_command(tn, "chmod 777 /data/video/" + args.folder + "/" + f[1]) - parrot_utils.execute_command(tn, "/data/video/" + args.folder + "/" + f[1] + " > /dev/null 2>&1 &") - print("#pragma message: Upload to, and start of Autopilot on, ARDrone2 successful !") - -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/video/" + args.folder) - print('Uploading \'' + f[1] + "\' from " + f[0] + " to /data/video/" + args.folder) - parrot_utils.uploadfile(ftp, args.folder + "/" + f[1], file(args.file, "rb")) - print("#pragma message: Upload of " + f[1] + " to ARDrone2 successful !") - -elif args.command == 'download_file': - # Split filename and path - f = parrot_utils.split_into_path_and_file(args.file) - # Open file and download - try: - file = open(args.file, 'wb') - print('Downloading \'' + f[1] + "\' from " + args.folder + " to " + f[0]) - ftp.retrbinary("RETR " + args.folder + "/" + f[1], file.write) - print("#pragma message: Download of " + f[1] + " from ARDrone2 successful !") - except IOError: - print("#pragma message: Fail to open file " + args.file) - except: - os.remove(args.file) - print("#pragma message: Download of " + f[1] + " from ARDrone2 Failed!") - else: - file.close() - -elif args.command == 'download_dir': - # Split filename and path - files = parrot_utils.execute_command(tn, 'find /data/video/' + 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: - file = open(file_dest, 'wb') - print('Downloading \'' + f + "\' to " + file_dest) - ftp.retrbinary("RETR " + file_source, file.write) - except IOError: - print("#pragma message: Fail to open file " + file_dest) - except: - os.remove(file_dest) - print("#pragma message: Download of " + f + " from ARDrone2 Failed!") + # Search for the name + search = re.search(name + '[^=]+=[\r\n\t ]([^\r\n\t ]+)',self.config_content) + if search is None: + return None else: - file.close() - print("#pragma message: End download of folder " + args.folder + " from ARDrone2") + return search.group(1) -elif args.command == 'rm_dir': - # Split filename and path - print("Deleting folder /data/video/" + args.folder + " from ARDrone2...") - print(parrot_utils.execute_command(tn, 'rm -r /data/video/' + args.folder)) + # Write to config + def write_to_config(self, name, value): + if self.read_from_config(name) == None: + self.execute_command('echo "' + name + ' = ' + value + '\" >> ' + self.config_file) + else: + self.execute_command('sed -i "s/\(' + name + ' *= *\).*/\\1' + value + '/g" ' + self.config_file) + + def uav_status(self): + print('Parrot version:\t\t' + self.check_version()) + print('Host address:\t\t' + self.address + + ' (' + self.read_from_config('static_ip_address_base', config_ini) + + self.read_from_config('static_ip_address_probe', config_ini) + ' after boot)') + print('Serial number:\t\t' + self.read_from_config('drone_serial')) + print('Network id:\t\t' + self.read_from_config('ssid_single_player')) + print('Motor software:\t\t' + + self.read_from_config('motor1_soft', config_ini) + '\t' + read_from_config('motor2_soft', config_ini) + '\t' + + self.read_from_config('motor3_soft', config_ini) + '\t' + read_from_config('motor4_soft', config_ini)) + print('Motor hardware:\t\t' + + self.read_from_config('motor1_hard', config_ini) + '\t' + read_from_config('motor2_hard', config_ini) + '\t' + + self.read_from_config('motor3_hard', config_ini) + '\t' + read_from_config('motor4_hard', config_ini)) + sleep(2.0) #Wait running process reporting back lag + print('Currently running:\t' + self.check_running()) + autorun = {'': 'Native', '0': 'Native', '1': 'Paparazzi'} + if self.check_autoboot(): + print('Autorun at start:\tInstalled booting ' + autorun[self.read_from_config('start_paparazzi', config_ini)]) + else: + print('Autorun at start:\tNot installed') + + # Check if the vision framework is installed and running + vision_framework = "" + if self.check_vision_installed(): + vision_framework += "Installed" + if self.check_vision_running(): + vision_framework += " and running" + print('Vision framework:\t' + vision_framework) -# Close the telnet and python script -parrot_utils.disconnect(tn, ftp) -exit(0) + # Check if vision framework is installed + def check_vision_installed(self): + du_opt = self.execute_command('du -d 2 /data/video/opt') + return '/data/video/opt/arm/gst' in du_opt or '/data/video/opt/arm/lib' in du_opt or '/data/video/opt/arm/tidsp-binaries-23.i3.8' in du_opt + + # Check if the vision framework is running + def check_vision_running(self): + du_opt = self.execute_command('du -d 2 /opt') + return '/opt/arm/gst' in du_opt and '/opt/arm/lib' in du_opt and '/opt/arm/tidsp-binaries-23.i3.8' in du_opt + + # Check if autoboot is installed + def check_autoboot(self): + check_update = self.execute_command('grep "START_PAPARAZZI" /bin/check_update.sh') + wifi_setup = self.execute_command('grep "BASE_ADRESS" /bin/wifi_setup.sh') + if "START_PAPARAZZI" in check_update and "BASE_ADRESS" in wifi_setup: + return True + else: + return False + + # Check if custom wifi_setup script is installed + def check_wifi_setup(self): + check_wifi = self.execute_command('grep "static_ip_address_base" /bin/wifi_setup.sh') + if "static_ip_address_base" in check_wifi: + return True + else: + return False + + # Install the vision framework + def ardrone2_install_vision(self): + print('Uploading GST') + self.upload_file("arm_light.tgz") + print(self.execute_command("cd /data/video && tar -xzf arm_light.tgz")) + print(self.execute_command("rm -rf /data/video/arm_light.tgz")) + print('Now Starting Vision') + self.ardrone2_start_vision() + + # Remove the vision framework + def ardrone2_remove_vision(self): + self.execute_command("rm -rf /opt/arm") + self.execute_command("rm -rf /lib/dsp") + self.execute_command("rm -rf /data/video/opt") + + # Start the vision framework + def ardrone2_start_vision(self): + # Mount the directories + self.execute_command("mkdir -p /opt/arm") + self.execute_command("mkdir -p /lib/dsp") + self.execute_command("mount --bind /data/video/opt/arm /opt/arm") + self.execute_command("mount --bind /data/video/opt/arm/lib/dsp /lib/dsp") + # Start The DSP programs + self.execute_command("kill -9 `pidof program.elf`") + self.execute_command("kill -9 `pidof gst-launch-0.10`") + self.execute_command("export PATH=/opt/arm/gst/bin:$PATH") + self.execute_command("export DSP_PATH=/opt/arm/tidsp-binaries-23.i3.8/") + self.execute_command("/bin/dspbridge/cexec.out -T /opt/arm/tidsp-binaries-23.i3.8/baseimage.dof -v") + self.execute_command("/bin/dspbridge/dynreg.out -r /opt/arm/tidsp-binaries-23.i3.8/m4venc_sn.dll64P -v") + # Show result + self.execute_command("ls -altr /opt/arm/gst/bin") + + # Install autoboot script + def ardrone2_install_autoboot(self): + print('Uploading autoboot script') + self.upload_file("ardrone2/check_update.sh") + print(self.execute_command("mv /data/video/check_update.sh /bin/check_update.sh")) + print(self.execute_command("chmod 777 /bin/check_update.sh")) + + # Install network script + def ardrone2_install_network_script(self): + print('Uploading Wifi script') + self.upload_file("ardrone2/wifi_setup.sh") + print(self.execute_command("mv /data/video/wifi_setup.sh /bin/wifi_setup.sh")) + print(self.execute_command("chmod 777 /bin/wifi_setup.sh")) + + # Install olsr deamon + def ardrone2_install_olsrd(self): + print('Uploading olsr deamon') + self.upload_file("ardrone2/olsrd") + self.upload_file("ardrone2/olsrd.conf") + print(self.execute_command("mv /data/video/olsrd /bin/olsrd")) + print(self.execute_command("chmod 777 /bin/olsrd")) + print(self.execute_command("mkdir -p /etc/olsrd")) + print(self.execute_command("mv /data/video/olsrd.conf /etc/olsrd")) + print(self.execute_command("rm -f /var/run && ln -s /tmp /var/run")) # olsrd needs /var/run folder, symlinked to /tmp + + # Set network SSID + def ardrone2_set_ssid(self, name): + write_to_config('ssid_single_player', name) + print('The network ID (SSID) of the ARDrone 2 is changed to ' + name) + + # Set IP address + def ardrone2_set_ip_address(self, address): + splitted_ip = address.split(".") + write_to_config('static_ip_address_base', splitted_ip[0] + '.' + splitted_ip[1] + '.' + splitted_ip[2] + '.') + write_to_config('static_ip_address_probe', splitted_ip[3]) + print('The IP Address of the ARDrone 2 is changed to ' + address) + + # Set wifi mode (0: master, 1: ad-hoc, 2: managed, *: master) + def ardrone2_set_wifi_mode(self, mode): + modes = { 'master' : '0', 'ad-hoc' : '1', 'managed' : '2', 'ad-hoc-olsr' : '3' } + try: + val = modes[mode] + except: + print('Unexpected wifi mode, setting to master (default)') + val = modes['master'] + write_to_config('wifi_mode', val) + print('The Wifi mode of the ARDrone2 is changed to ' + mode + ' (' + val + ')') + + # Set network channel + def ardrone2_set_wifi_channel(self, chan): + write_to_config('wifi_channel', chan) + print('The network channel of the ARDrone 2 is changed to ' + chan) + + def init_extra_parser(self): + # Parse custom arguments + self.subparsers.add_parser('installvision', help='Install the vision framework') + self.subparsers.add_parser('startvision', help='Start the vision framework') + ss = self.subparsers.add_parser('upload_gst_module', + help='Upload, configure and move a gstreamer0.10 module libXXX.so') + ss.add_argument('file', help='Filename of *.so module') + + ss = self.subparsers.add_parser('networkid', help='Set the network ID(SSID) of the ARDrone 2') + ss.add_argument('name', help='the new network ID(SSID)') + ss = self.subparsers.add_parser('ipaddress', help='Set the IP address of the ARDrone 2') + ss.add_argument('address', help='the new IP address') + ss = self.subparsers.add_parser('wifimode', help='Set the Wifi mode the ARDrone 2') + ss.add_argument('mode', help='the new Wifi mode', choices=['master', 'ad-hoc', 'managed', 'ad-hoc-olsr']) + ss = self.subparsers.add_parser('configure_network', help='Configure the network on the ARDrone 2') + ss.add_argument('name', help='the new network ID(SSID)') + ss.add_argument('address', help='the new IP address') + ss.add_argument('mode', help='the new Wifi mode', choices=['master', 'ad-hoc', 'managed', 'ad-hoc-olsr']) + ss.add_argument('--channel', help='the wifi channel (auto or 1 to 11)', default='auto') + ss = self.subparsers.add_parser('install_autostart', help='Install custom autostart script and set what to start on boot for the ARDrone 2') + ss.add_argument('type', choices=['native', 'paparazzi'], + help='what to start on boot') + ss = self.subparsers.add_parser('autostart', help='Set what to start on boot for the ARDrone 2') + ss.add_argument('type', choices=['native', 'paparazzi'], + help='what to start on boot') + + def parse_extra_args(self, args): + + # Change the network ID + if args.command == 'networkid': + self.ardrone2_set_ssid(args.name) + if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': + self.reboot() + + # Change the IP address + elif args.command == 'ipaddress': + self.ardrone2_set_ip_address(args.address) + if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': + self.reboot() + + # Change the wifi mode + elif args.command == 'wifimode': + self.ardrone2_set_wifi_mode(args.mode) + if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': + self.reboot() + + # Install and configure network + elif args.command == 'configure_network': + config_ini = self.execute_command('cat /data/config.ini') + print('=== Current network setup ===') + print('Network id:\t' + self.read_from_config('ssid_single_player', config_ini)) + print('Host:\t\t' + args.host + ' (' + read_from_config('static_ip_address_base', config_ini) + + self.read_from_config('static_ip_address_probe', config_ini) + ' after boot)') + print('Mode:\t\t' + self.read_from_config('wifi_mode', config_ini)) + print('Channel:\t' + self.read_from_config('wifi_channel', config_ini)) + print('=============================') + if self.check_wifi_setup(): + print('Custom Wifi script already installed') + if raw_input("Shall I reinstall the Wifi script (y/N) ").lower() == 'y': + self.ardrone2_install_network_script() + else: + if raw_input("Shall I install custom Wifi script (recommanded) (y/N) ").lower() == 'y': + self.ardrone2_install_network_script() + if raw_input("Shall I install olsrd (ad-hoc wireless mesh routing deamon) (y/N) ").lower() == 'y': + self.ardrone2_install_olsrd() + self.ardrone2_set_ssid(args.name) + self.ardrone2_set_ip_address(args.address) + self.ardrone2_set_wifi_mode(args.mode) + self.ardrone2_set_wifi_channel(args.channel) + config_ini = self.execute_command('cat /data/config.ini') + print('== New network setup after boot ==') + print('Network id:\t' + self.read_from_config('ssid_single_player', config_ini)) + print('Host:\t\t' + self.read_from_config('static_ip_address_base', config_ini) + + self.read_from_config('static_ip_address_probe', config_ini)) + print('Mode:\t\t' + self.read_from_config('wifi_mode', config_ini)) + print('Channel:\t' + self.read_from_config('wifi_channel', config_ini)) + print('==================================') + + if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': + self.reboot() + + # Install and configure autostart + elif args.command == 'install_autostart': + if self.check_autoboot(): + print('Custom autostart script already installed') + if raw_input("Shall I reinstall the autostart script (y/N) ").lower() == 'y': + self.ardrone2_install_autoboot() + else: + self.ardrone2_install_autoboot() + autorun = {'native': '0', 'paparazzi': '1'} + self.write_to_config('start_paparazzi', autorun[args.type]) + print('The autostart on boot is changed to ' + args.type) + + if raw_input("Shall I restart the ARDrone 2? (y/N) ").lower() == 'y': + self.reboot() + + # Change the autostart + elif args.command == 'autostart': + autorun = {'native': '0', 'paparazzi': '1'} + self.write_to_config('start_paparazzi', autorun[args.type]) + print('The autostart on boot is changed to ' + args.type) + + # Install Vision framework + elif args.command == 'installvision': + if self.check_vision_installed(): + print('Vision framework already installed') + if raw_input("Shall I reinstall the vision framework? (y/N) ").lower() == 'y': + self.ardrone2_remove_vision() + self.ardrone2_install_vision() + + self.ardrone2_install_vision() + print('Vision framework installed') + + # Start Vision framework + elif args.command == 'startvision': + if self.check_vision_running(): + print('Vision framework already started') + else: + if not self.check_vision_installed(): + print('No vision framework installed') + if raw_input("Shall I install the vision framework? (y/N) ").lower() == 'y': + self.ardrone2_install_vision() + + if self.check_vision_installed(): + self.ardrone2_start_vision() + print('Vision framework started') + + elif args.command == 'upload_gst_module': + print('Uploading ...' + args.file) + self.upload_file(args.file) + self.execute_command("chmod 777 /data/video/" + args.file) + self.execute_command("mv /data/video/" + args.file + " /data/video/opt/arm/gst/lib/gstreamer-0.10") + if self.check_vision_running(): + print('Info: Vision framework already started') + else: + if not self.check_vision_installed(): + print('Warning: No vision framework installed') + if raw_input("Warning: Shall I install the vision framework? (y/N) ").lower() == 'y': + self.ardrone2_install_vision() + + if self.check_vision_installed(): + self.ardrone2_start_vision() + print('#pragma message: Vision framework started') + print('#pragma message: Vision Plugin Uploaded and DSP Started.') + + +if __name__ == "__main__": + ardrone2 = Ardrone2() + ardrone2.parse_args() + exit(0) + diff --git a/sw/tools/parrot/bebop.py b/sw/tools/parrot/bebop.py index 49999f8dd1..eabd322b31 100755 --- a/sw/tools/parrot/bebop.py +++ b/sw/tools/parrot/bebop.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # # Copyright (C) 2012-2014 The Paparazzi Team +# 2015 Freek van Tienen +# 2017 Gautier Hattenberger # # 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) diff --git a/sw/tools/parrot/parrot_utils.py b/sw/tools/parrot/parrot_utils.py index 11a0f1e10f..5da91e77f6 100644 --- a/sw/tools/parrot/parrot_utils.py +++ b/sw/tools/parrot/parrot_utils.py @@ -1,5 +1,7 @@ # # Copyright (C) 2012-2014 The Paparazzi Team +# 2015 Freek van Tienen +# 2017 Gautier Hattenberger # # 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() diff --git a/sw/tools/parrot/swing.py b/sw/tools/parrot/swing.py index 15684b14da..ac4771c2ac 100755 --- a/sw/tools/parrot/swing.py +++ b/sw/tools/parrot/swing.py @@ -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)