From 3997952e1eec35e814e99823ece3f59413e4376f Mon Sep 17 00:00:00 2001 From: Igor Nurullaev Date: Thu, 29 Aug 2019 20:39:51 +0300 Subject: [PATCH] Added file transfer (server => copter) --- Server/app_routes/file_sender.py | 38 ++++++++++++----- Server/app_routes/misc.py | 57 +++++++++++++++++++++++++- Server/static/js/file.js | 32 ++++++++++++++- Server/static/js/main.js | 70 ++++++++++++++++++++++++++------ Server/templates/main.html | 13 +++++- Server/web_server.py | 17 +++++++- 6 files changed, 198 insertions(+), 29 deletions(-) diff --git a/Server/app_routes/file_sender.py b/Server/app_routes/file_sender.py index eb089a4..8e82c64 100644 --- a/Server/app_routes/file_sender.py +++ b/Server/app_routes/file_sender.py @@ -1,17 +1,11 @@ +import os +from json import loads from flask import Blueprint, request, jsonify from web_server_models import copters file_sender_api = Blueprint('file_sender_api', __name__, template_folder='templates') -@file_sender_api.route('/set/animation', methods=['GET', 'POST']) -def set_animation(): - if request.method == 'POST': - f = request.files['file'] - print(f, 'ip', request.args.get('ip')) - return jsonify({'m': 'ok'}) - - @file_sender_api.route('/set/config', methods=['GET', 'POST']) def set_config(): if request.method == 'POST': @@ -23,6 +17,30 @@ def set_config(): @file_sender_api.route('/set/aruco', methods=['GET', 'POST']) def set_aruco(): if request.method == 'POST': - f = request.files['file'] - print(f, 'ip', request.args.get('ip')) + for key_name in request.files.keys(): + request.files[key_name].save(os.path.join('files', key_name)) + for ip in loads(request.args.get('ips')): + for copter in copters: + if copter.ip == ip: + copter.client.send_file('files/' + key_name, "/home/pi/catkin_ws/src/clever/aruco_pose/map/animation_map.txt") + copter.client.send_message("service_restart", {"name": "clever"}) + os.remove('files/' + key_name) + return jsonify({'m': 'ok'}) + + +@file_sender_api.route('/set/animation', methods=['GET', 'POST']) +def set_animation(): + if request.method == 'POST': + files = [] + names = [] + for key_name in request.files.keys(): + names.append(key_name.replace('.csv', '')) + request.files[key_name].save(os.path.join('files', key_name)) + files.append('files/' + key_name) + for file, name in zip(files, names): + for copter in copters: + if name == copter.name: + copter.client.send_file(file, "animation.csv") + for filename in files: + os.remove(filename) return jsonify({'m': 'ok'}) diff --git a/Server/app_routes/misc.py b/Server/app_routes/misc.py index e78f5b6..6263612 100644 --- a/Server/app_routes/misc.py +++ b/Server/app_routes/misc.py @@ -1,5 +1,6 @@ from flask import Blueprint, request, jsonify -from web_server_models import delay, set_delay_manually, get_delay_manually +from web_server_models import set_delay_manually, get_delay_manually, copters +from server import Client misc_api = Blueprint('misc_api', __name__, template_folder='templates') @@ -13,3 +14,57 @@ def set_delay(): @misc_api.route('/get/delay', methods=['GET', 'POST']) def get_delay(): return jsonify(get_delay_manually()) + + +@misc_api.route('/stop/all', methods=['GET', 'POST']) +def stop_all(): + Client.broadcast_message("stop") + return jsonify({'m': 'ok'}) + + +@misc_api.route('/disarm/all', methods=['GET', 'POST']) +def disarm_all(): + Client.broadcast_message("disarm") + return jsonify({'m': 'ok'}) + + +@misc_api.route('/land/all', methods=['GET', 'POST']) +def land_all(): + Client.broadcast_message("land") + return jsonify({'m': 'ok'}) + + +@misc_api.route('/flip/selected', methods=['GET', 'POST']) +def flip_selected(): + ip = request.args.get("ip") + for copter in copters: + if copter.ip == ip: + copter.client.send_message("flip") + return jsonify({'m': 'ok'}) + + +@misc_api.route('/takeoff/selected', methods=['GET', 'POST']) +def takeoff_selected(): + ip = request.args.get("ip") + for copter in copters: + if copter.ip == ip: + copter.client.send_message("takeoff") + return jsonify({'m': 'ok'}) + + +@misc_api.route('/pause/selected', methods=['GET', 'POST']) +def pause_selected(): + ip = request.args.get("ip") + for copter in copters: + if copter.ip == ip: + copter.client.send_message("pause") + return jsonify({'m': 'ok'}) + + +@misc_api.route('/resume/selected', methods=['GET', 'POST']) +def resume_selected(): + ip = request.args.get("ip") + for copter in copters: + if copter.ip == ip: + copter.client.send_message("resume") + return jsonify({'m': 'ok'}) diff --git a/Server/static/js/file.js b/Server/static/js/file.js index d4e45aa..562c989 100644 --- a/Server/static/js/file.js +++ b/Server/static/js/file.js @@ -3,13 +3,41 @@ let configInput = document.getElementById('configFile'); let arucoInput = document.getElementById('arucoFile'); animationInput.onchange = function (e) { - sendRows(table.getSelectedRows(), animationInput.files[0], 'animation'); + spinner.style.display = 'inline-block'; + setTimeout(function () { + if (animationInput.files.length > 0) { + let fileReq = new XMLHttpRequest(); + let fileFormData = new FormData(); + for (let i = 0; i < animationInput.files.length; i++) { + fileFormData.append(animationInput.files[i].name, animationInput.files[i]); + } + fileReq.open("POST", '/set/animation', false); + fileReq.send(fileFormData); + deselectAll(); + spinner.style.display = 'none'; + } + }, 20); }; configInput.onchange = function (e) { sendRows(table.getSelectedRows(), configInput.files[0], 'config'); }; arucoInput.onchange = function (e) { - sendRows(table.getSelectedRows(), arucoInput.files[0], 'aruco'); + spinner.style.display = 'inline-block'; + setTimeout(function () { + if (arucoInput.files.length > 0) { + let fileReq = new XMLHttpRequest(); + let fileFormData = new FormData(); + let ips = []; + table.getSelectedRows().forEach(function (element) { + ips.push(element._row.data.ip); + }); + fileFormData.append(arucoInput.files[0].name, arucoInput.files[0]); + fileReq.open("POST", '/set/aruco?ips=' + encodeURIComponent(JSON.stringify(ips)), false); + fileReq.send(fileFormData); + deselectAll(); + spinner.style.display = 'none'; + } + }, 20); }; function sendRows(selectedRows, file, file_type) { diff --git a/Server/static/js/main.js b/Server/static/js/main.js index eaa033f..2b6a3ad 100644 --- a/Server/static/js/main.js +++ b/Server/static/js/main.js @@ -77,30 +77,28 @@ function deselectAll() { }); } -function testLedSelected() { +function sendCommandToSelected(command) { spinner.style.display = 'inline-block'; setTimeout(function () { table.getSelectedRows().forEach(function (element) { let req = new XMLHttpRequest(); - req.open('POST', '/test_led/selected?ip=' + element._row.data.ip); + req.open('POST', '/' + command + '/selected?ip=' + element._row.data.ip); req.send(); + element.deselect(); }); deselectAll(); spinner.style.display = 'none'; }, 20); } -function pauseCopters() { - +function testLedSelected() { + sendCommandToSelected('test_led'); } function stopCopters() { - -} - - -function emLand() { - + let req = new XMLHttpRequest(); + req.open('POST', '/stop/all', false); + req.send(); } function setStartTime() { @@ -108,11 +106,57 @@ function setStartTime() { title: "Set animation delay", form: {delay: "Delay"} }).done(function (ui) { - setDelay(parseInt(ui.data.delay)); - updateDelay(); + if (ui.state) { + setDelay(parseInt(ui.data.delay)); + updateDelay(); + } }); } -function startAnimation() { +function takeOff() { + sendCommandToSelected('takeoff'); +} +function flipCopters() { + sendCommandToSelected('flip'); +} + +function land() { + let req = new XMLHttpRequest(); + req.open('POST', '/land/all', false); + req.send(); +} + +function disarm() { + let req = new XMLHttpRequest(); + req.open('POST', '/disarm/all', false); + req.send(); +} + +function pauseCopters() { + sendCommandToSelected('pause'); +} + +function resumeCopters() { + sendCommandToSelected('resume'); +} + +function emLand() { + spinner.style.display = 'inline-block'; + setTimeout(function () { + let req = new XMLHttpRequest(); + req.open('POST', '/em_land', false); + req.send(); + spinner.style.display = 'none'; + }, 20); +} + +function startAnimation() { + spinner.style.display = 'inline-block'; + setTimeout(function () { + let req = new XMLHttpRequest(); + req.open('POST', '/start_animation', false); + req.send(); + spinner.style.display = 'none'; + }, 20); } \ No newline at end of file diff --git a/Server/templates/main.html b/Server/templates/main.html index eb05fd5..fdd7490 100644 --- a/Server/templates/main.html +++ b/Server/templates/main.html @@ -28,7 +28,7 @@ @@ -78,11 +78,20 @@
+
+
+ + +
+
+ + +
diff --git a/Server/web_server.py b/Server/web_server.py index 757c707..da89676 100644 --- a/Server/web_server.py +++ b/Server/web_server.py @@ -1,5 +1,6 @@ from server import Server -from flask import Flask, render_template +from web_server_models import copters, get_delay_manually +from flask import Flask, render_template, jsonify, request from app_routes.selfcheck import selfcheck_api, refresh_copters from app_routes.file_sender import file_sender_api from app_routes.misc import misc_api @@ -17,6 +18,20 @@ def home(): return render_template('main.html', data=data) +@app.route('/start_animation', methods=['GET', 'POST']) +def resume_selected(): + for copter in copters: + server.send_starttime(copter.client, get_delay_manually()) + return jsonify({'m': 'ok'}) + + +@app.route('/em_land', methods=['GET', 'POST']) +def em_land_selected(): + for copter in copters: + copter.client.send_message("land") + return jsonify({'m': 'ok'}) + + server = Server() server.start() app.run(host='0.0.0.0', debug=False)