diff --git a/Drone/client.py b/Drone/client.py index 43f9b74..315168e 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -148,18 +148,18 @@ class Client(object): message = messaging.MessageManager() message.income_raw = data message.process_message() - if message.content and message.jsonheader["action"] == "server_ip": + if message.content: logger.info("Received broadcast message {} from {}".format(message.content, addr)) + if message.content["command"] == "server_ip": + args = message.content["args"] + self.config.set("SERVER", "port", int(args["port"])) + self.config.set("SERVER", "host", args["host"]) + self.config.write() - kwargs = message.content["kwargs"] - self.config.set("SERVER", "port", int(kwargs["port"])) - self.config.set("SERVER", "host", kwargs["host"]) - self.config.write() - - logger.info("Binding to new IP: {}:{}".format( - self.config.server_host, self.config.server_port)) - self.on_broadcast_bind() - break + logger.info("Binding to new IP: {}:{}".format( + self.config.server_host, self.config.server_port)) + self.on_broadcast_bind() + break finally: broadcast_client.close() @@ -168,7 +168,6 @@ class Client(object): def _process_connections(self): while True: - #self.server_connection.send_message("telemetry", kwargs={"value":{"time": time.time()}}) events = self.selector.select(timeout=1) for key, mask in events: @@ -227,7 +226,6 @@ def _response_id(*args, **kwargs): if new_id is not None: active_client.config.set("PRIVATE", "id", new_id, True) active_client.load_config() - # TODO renaming here return active_client.client_id diff --git a/Drone/copter_client.py b/Drone/copter_client.py index 597e6c1..7b42a54 100644 --- a/Drone/copter_client.py +++ b/Drone/copter_client.py @@ -123,7 +123,7 @@ def execute_command(command): os.system(command) -def configure_chrony_ip(ip, path="/etc/chrony/chrony.conf", ip_index=1): # TODO simplify +def configure_chrony_ip(ip, path="/etc/chrony/chrony.conf", ip_index=1): try: with open(path, 'r') as f: raw_content = f.read() @@ -245,7 +245,7 @@ def _execute(*args, **kwargs): logger.info("Executing done") -@messaging.message_callback("id") # TODO redo +@messaging.message_callback("id") def _response_id(*args, **kwargs): new_id = kwargs.get("new_id", None) if new_id is not None: @@ -645,7 +645,6 @@ def _play_animation(*args, **kwargs): ) -# noinspection PyAttributeOutsideInit class Telemetry: params_default_dict = { "git_version": None, @@ -653,14 +652,13 @@ class Telemetry: "battery": None, "armed": False, "fcu_status": None, - "calibration_status": None, + "cal_status": None, "mode": None, "selfcheck": None, "current_position": None, "start_position": None, "task": None, "time": None, - "config_version": None, } def __init__(self): @@ -692,10 +690,6 @@ class Telemetry: def get_git_version(cls): return subprocess.check_output("git log --pretty=format:'%h' -n 1", shell=True) - @classmethod - def get_config_version(cls): - return "{} V{}".format(client.active_client.config.config_name, client.active_client.config.config_version) - @classmethod def get_start_position(cls): x_start, y_start = animation.get_start_xy(os.path.abspath("animation.csv"), @@ -770,7 +764,6 @@ class Telemetry: def update_telemetry_slow(self): self.animation_id = animation.get_id() self.git_version = self.get_git_version() - self.config_version = self.get_config_varsion() try: self.cal_status = get_calibration_status() self.fcu_status = get_sys_status() @@ -835,9 +828,9 @@ class Telemetry: self._tasks_cleared = False self._last_state = state - def transmit_message(self): # todo if connected + def transmit_message(self): try: - client.active_client.server_connection.send_message('telemetry', kwargs={'value': self.create_msg_contents()}) + client.active_client.server_connection.send_message('telemetry', args={'value': self.create_msg_contents()}) except AttributeError as e: logger.debug(e) diff --git a/Server/config/spec/configspec_server.ini b/Server/config/spec/configspec_server.ini index b0efd85..905a6be 100644 --- a/Server/config/spec/configspec_server.ini +++ b/Server/config/spec/configspec_server.ini @@ -24,7 +24,6 @@ remove_disconnected = boolean(default=False) start_position = boolean(default=True) last_task = boolean(default=True) time_delta = boolean(default=True) - config_version = boolean(default=True) [[[__many__]]] __many__ = boolean diff --git a/Server/config_editor_models.py b/Server/config_editor_models.py index 898db7b..cf5dec2 100644 --- a/Server/config_editor_models.py +++ b/Server/config_editor_models.py @@ -372,7 +372,7 @@ class ConfigModel(QtCore.QAbstractItemModel): return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction def mimeTypes(self): - return ['app/configitem'] + return ['app/configitem', 'text/xml'] def mimeData(self, indexes): mimedata = QtCore.QMimeData() diff --git a/Server/copter_table.py b/Server/copter_table.py index 725c12b..b9b3a15 100644 --- a/Server/copter_table.py +++ b/Server/copter_table.py @@ -49,10 +49,8 @@ class CopterTableWidget(QTableView): self.setSortingEnabled(True) self.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) self.resizeColumnsToContents() - self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems) - self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) + self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.doubleClicked.connect(self.on_double_click) - self.setDragEnabled(True) def moved(self, logical_index, old_index, new_index): name = self.current_columns.pop(old_index) diff --git a/Server/copter_table_models.py b/Server/copter_table_models.py index d414760..b992aaf 100644 --- a/Server/copter_table_models.py +++ b/Server/copter_table_models.py @@ -1,14 +1,12 @@ import re import sys -import os import time import math import indexed -from contextlib import suppress from PyQt5 import QtCore, QtGui, QtWidgets -from PyQt5.QtCore import Qt as Qt, QUrl, QDir -from PyQt5.QtWidgets import QApplication +from PyQt5.QtCore import Qt as Qt + ModelDataRole = 998 ModelStateRole = 999 @@ -118,18 +116,15 @@ columns_names = {'copter_id': 'copter ID', 'current_position': 'current x y z yaw frame_id', 'start_position': ' start x y z ', 'last_task': 'last task', - 'time_delta': 'dt', - 'config_version': 'configuration', + 'time_delta': 'dt' } -columns = list(columns_names.keys()) class CopterData: class_basic_attrs = indexed.IndexedOrderedDict([('copter_id', None), ('git_ver', None), ('animation_id', None), - ('battery', None), ('fcu_status', None), ('calibration_status', None), + ('battery', None), ('fcu_status', None), ('cal_status', None), ('mode', None), ('selfcheck', None), ('current_position', None), - ('start_position', None), ('last_task', None), ('time_delta', None), - ("config_version", None), ('client', None)]) + ('start_position', None), ('last_task', None), ('time_delta', None), ('client', None)]) def __init__(self, **kwargs): self.attrs_dict = self.class_basic_attrs.copy() @@ -304,11 +299,7 @@ def place_time_delta(value): @ModelFormatter.col_format(11, ModelFormatter.VIEW_FORMATTER) def view_time_delta(value): - return "{:.3f}".format(value) - - -def is_column(index, column_name): - return index.column() == columns.index(column_name) + return "{:.3f}".format(value) class CopterDataModel(QtCore.QAbstractTableModel): @@ -479,7 +470,7 @@ class CopterDataModel(QtCore.QAbstractTableModel): self.update_model(index, role) return True - def select_all(self): # probably NOT thread-safe! TODO remake + def select_all(self): # probably NOT thread-safe! self.first_col_is_checked = not self.first_col_is_checked for row_num, copter in enumerate(self.data_contents): copter.states.checked = int(self.first_col_is_checked)*2 @@ -489,37 +480,8 @@ class CopterDataModel(QtCore.QAbstractTableModel): roles = Qt.ItemIsSelectable | Qt.ItemIsEnabled if index.column() == 0: roles |= Qt.ItemIsUserCheckable | Qt.ItemIsEditable - if is_column(index, "config_version"): - roles |= Qt.ItemIsDragEnabled # | Qt.ItemIsDropEnabled - return roles - def supportedDropActions(self): - return QtCore.Qt.CopyAction - - def mimeTypes(self): - return ['text/plain'] - - def mimeData(self, indexes): - index = indexes[0] - if is_column(index, "config_version"): - return self._config_mime(index) - - return None - - def _config_mime(self, index): - mimedata = QtCore.QMimeData() - path = os.path.join(QDir.tempPath(), "config_{}.ini".format( - self.data_contents[index.row()].copter_id)) - - with suppress(OSError): # remove if file exists - os.remove(path) - - self.data_contents[index.row()].client.get_file("config/client.ini", path,) - mimedata.setUrls([QUrl.fromLocalFile(path)]) - - return mimedata - @QtCore.pyqtSlot(int, int, QtCore.QVariant, QtCore.QVariant) def update_item(self, row, col, value, role=Qt.EditRole): self.setData(self.index(row, col), value, role) diff --git a/Server/server.py b/Server/server.py index 3e6e21c..94be295 100644 --- a/Server/server.py +++ b/Server/server.py @@ -8,7 +8,6 @@ import datetime import threading import selectors import collections -import traceback import inspect # Add parent dir to PATH to import messaging_lib and config_lib @@ -157,7 +156,6 @@ class Server(messaging.Singleton): client.process_events(mask) except Exception as error: logging.error("Exception {} occurred for {}! Resetting connection!".format(error, client.addr)) - traceback.print_exc() client.close(True) else: # Notifier client.process_events(mask) @@ -187,9 +185,9 @@ class Server(messaging.Singleton): def _ip_broadcast(self): logging.info("Broadcast sender thread started!") - msg = messaging.MessageManager.create_action_message( - "server_ip", kwargs={"host": self.ip, "port": str(self.config.server_port), "id": self.id, - "start_time": str(self.time_started)}) + msg = messaging.MessageManager.create_simple_message( + "server_ip", {"host": self.ip, "port": str(self.config.server_port), "id": self.id, + "start_time": str(self.time_started)}) logging.debug("Formed broadcast message: {}".format(msg)) broadcast_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) @@ -233,11 +231,11 @@ class Server(messaging.Singleton): message.process_message() content = message.content - right_command = (content and message.jsonheader["action"] == "server_ip") + right_command = (content and content["command"] == "server_ip") if right_command: - different_id = content["kwargs"]["id"] != str(self.id) - self_younger = float(content["kwargs"]["start_time"]) <= self.time_started + different_id = content["args"]["id"] != str(self.id) + self_younger = float(message.content["args"]["start_time"]) <= self.time_started if different_id and self_younger: # younger server should shut down @@ -255,7 +253,7 @@ class Server(messaging.Singleton): logging.info("Broadcast listener thread stopped, socked closed!") def send_starttime(self, copter, start_time): - copter.send_message("start", kwargs={"time": str(start_time)}) + copter.send_message("start", {"time": str(start_time)}) def requires_connect(f): @@ -358,7 +356,7 @@ class Client(messaging.ConnectionManager): @classmethod @requires_any_connected def broadcast_message(cls, command, args=None, force_all=False): - cls.broadcast(messaging.MessageManager.create_action_message(command, args), force_all) + cls.broadcast(messaging.MessageManager.create_simple_message(command, args), force_all) if __name__ == '__main__': diff --git a/Server/server_qt.py b/Server/server_qt.py index 862741c..dc27723 100644 --- a/Server/server_qt.py +++ b/Server/server_qt.py @@ -127,7 +127,7 @@ class MainWindow(QtWidgets.QMainWindow): self.ui.action_send_any_file.triggered.connect(self.send_any_file) self.ui.action_send_any_command.triggered.connect(self.send_any_command) self.ui.action_restart_clever.triggered.connect( - b_partial(self.send_to_selected, "service_restart", kwargs={"name": "clever"})) + b_partial(self.send_to_selected, "service_restart", {"name": "clever"})) self.ui.action_restart_clever_show.triggered.connect(self.restart_clever_show) self.ui.action_update_client_repo.triggered.connect(b_partial(self.send_to_selected, "update_repo")) self.ui.action_reboot_all.triggered.connect(b_partial(self.send_to_selected, "reboot_all")) @@ -200,9 +200,8 @@ class MainWindow(QtWidgets.QMainWindow): yield f(copter, *args, **kwargs) @pyqtSlot() - def send_to_selected(self, command, command_args=(), command_kwargs=None): - return list(self.iterate_selected(lambda copter: copter.client.send_message( - command, command_args, command_kwargs))) + def send_to_selected(self, command, command_args=None): + return list(self.iterate_selected(lambda copter: copter.client.send_message(command, command_args))) def new_client_connected(self, client: Client): logging.debug("Added client {}".format(client)) @@ -238,14 +237,13 @@ class MainWindow(QtWidgets.QMainWindow): "animation_id": 2, "battery": 3, "fcu_status": 4, - "calibration_status": 5, + "cal_status": 5, "mode": 6, "selfcheck": 7, "current_position": 8, "start_position": 9, "task": 10, "time": 11, - "config_version": 12, } for key, value in telems.items(): @@ -288,7 +286,7 @@ class MainWindow(QtWidgets.QMainWindow): self.ui.pause_button.setText('Resume') else: time_gap = 0.1 # TODO config? automatic delay detection? - self.send_to_selected("resume", kwargs={"time": server.time_now() + time_gap}) + self.send_to_selected("resume", {"time": server.time_now() + time_gap}) self.ui.pause_button.setText('Pause') @pyqtSlot() @@ -297,7 +295,7 @@ class MainWindow(QtWidgets.QMainWindow): for copter in self.model.user_selected(): if self.model.checks.takeoff_checks(copter): if self.ui.z_checkbox.isChecked(): - copter.client.send_message("takeoff_z", {"z": str(self.ui.z_spin.value())}) # todo int, merge commands + copter.client.send_message("takeoff_z", {"z": str(self.ui.z_spin.value())}) # todo int else: copter.client.send_message("takeoff") @@ -427,7 +425,7 @@ class MainWindow(QtWidgets.QMainWindow): @pyqtSlot() def send_aruco(self): def callback(copter): - copter.client.send_message("service_restart", kwargs={"name": "clever"}) + copter.client.send_message("service_restart", {"name": "clever"}) self.send_files("Select aruco map configuration file", "Aruco map files (*.txt)", onefile=True, client_path="/home/pi/catkin_ws/src/clever/aruco_pose/map/", @@ -467,20 +465,20 @@ class MainWindow(QtWidgets.QMainWindow): copters = self.model.user_selected() for copter in copters: - copter.client.send_message("config", kwargs={"config": data, "mode": mode.lower()}) + copter.client.send_message("config", {"config": data, "mode": mode.lower()}) @pyqtSlot() def send_any_command(self): text, ok = QInputDialog.getText(self, "Enter command to send on copter", "Command:", QLineEdit.Normal, "") if ok and text: - self.send_to_selected("execute", kwargs={"command": text}) + self.send_to_selected("execute", {"command": text}) @pyqtSlot() def restart_clever_show(self): for copter in self.model.user_selected(): - copter.client.send_message("service_restart", kwargs={"name": "visual_pose_watchdog"}) - copter.client.send_message("service_restart", kwargs={"name": "clever-show"}) + copter.client.send_message("service_restart", {"name": "visual_pose_watchdog"}) + copter.client.send_message("service_restart", {"name": "clever-show"}) @pyqtSlot() def restart_chrony(self): diff --git a/messaging_lib.py b/messaging_lib.py index 5f49ee9..dab54f5 100644 --- a/messaging_lib.py +++ b/messaging_lib.py @@ -94,41 +94,35 @@ class MessageManager: return message @classmethod - def create_json_message(cls, contents, additional_headers=None): - message = cls.create_message(cls._json_encode(contents), "json", "message", - additional_headers=additional_headers) + def create_json_message(cls, contents): + message = cls.create_message(cls._json_encode(contents), "json", "message") return message @classmethod - def create_action_message(cls, action, args=(), kwargs=None): - if kwargs is None: - kwargs = {} - message = cls.create_json_message({"args": args, "kwargs": kwargs}, {"action": action, }) + def create_simple_message(cls, command, args=None): + if args is None: + args = {} + message = cls.create_json_message({"command": command, "args": args}) return message @classmethod - def create_request(cls, requested_value, request_id, args=(), kwargs=None): - if kwargs is None: - kwargs = {} + def create_request(cls, requested_value, request_id, args=None): + if args is None: + args = {} contents = {"requested_value": requested_value, "request_id": request_id, "args": args, - "kwargs": kwargs, } message = cls.create_message(cls._json_encode(contents), "json", "request") return message @classmethod - def create_response(cls, requested_value, request_id, value, filetransfer=False): - headers = {"requested_value": requested_value, - "request_id": request_id, # TODO status - } - if filetransfer: - contents = value - else: - contents = cls._json_encode({"value": value, }) - message = cls.create_message(contents, "binary" if filetransfer else "json", - "response", additional_headers=headers) + def create_response(cls, requested_value, request_id, value): + contents = {"requested_value": requested_value, + "request_id": request_id, + "value": value, + } + message = cls.create_message(cls._json_encode(contents), "json", "response") return message def _process_protoheader(self): @@ -177,10 +171,10 @@ class MessageManager: self._process_content() -def message_callback(action_string): +def message_callback(string_command): def inner(f): - ConnectionManager.messages_callbacks[action_string] = f - logger.debug("Registered message function {} for {}".format(f, action_string)) + ConnectionManager.messages_callbacks[string_command] = f + logger.debug("Registered message function {} for {}".format(f, string_command)) def wrapper(*args, **kwargs): return f(*args, **kwargs) @@ -346,105 +340,84 @@ class ConnectionManager(object): raise RuntimeError("Peer closed.") - def process_received(self, message): - message_type = message.jsonheader["message-type"] - content = message.content if message.jsonheader["content-type"] != "binary"\ - else message.content[:256] + def process_received(self, income_message): + message_type = income_message.jsonheader["message-type"] + content = income_message.content if message_type != "filetransfer" else income_message.content[:256] logger.debug( - "Received message! Header: {}, content: {}".format(message.jsonheader, content)) + "Received message! Header: {}, content: {}".format(income_message.jsonheader, content)) if message_type == "message": - self._process_message(message) + self._process_message(income_message) elif message_type == "response": - self._process_response(message) + self._process_response(income_message) elif message_type == "request": - self._process_request(message) + self._process_request(income_message) + elif message_type == "filetransfer": + self._process_filetransfer(income_message) def _process_message(self, message): - if message.jsonheader["action"] == "filetransfer": - self._process_filetransfer(message.content, message.jsonheader["filepath"]) - else: - self._process_action(message) - - def _process_action(self, message): - action = message.jsonheader["action"] + command = message.content["command"] args = message.content["args"] - kwargs = message.content["kwargs"] - callback = self.messages_callbacks.get(action, None) + callback = self.messages_callbacks.get(command, None) if callback is None: - logger.warning("Action {} does not exist!".format(action)) + logger.warning("Command {} does not exist!".format(command)) return try: - callback(self, *args, **kwargs) + callback(self, **args) except Exception as error: - logger.error("Error during action {} execution: {}".format(action, error)) + logger.error("Error during command {} execution: {}".format(command, error)) def _process_request(self, message): - requested_value = message.content["requested_value"] + command = message.content["requested_value"] request_id = message.content["request_id"] args = message.content["args"] - kwargs = message.content["kwargs"] - - filetransfer = requested_value == "filetransfer" + callback = self.requests_callbacks.get(command, None) + if callback is None: + logger.warning("Request {} does not exist!".format(command)) + return try: - if filetransfer: - value = self._read_file(kwargs["filepath"]) - else: - callback = self.requests_callbacks.get(requested_value, None) - if callback is None: - logger.warning("Request {} does not exist!".format(requested_value)) - return - - value = callback(self, *args, **kwargs) + value = callback(self, **args) except Exception as error: # TODO send response error\cancel - logger.error("Error during request {} processing: {}".format(requested_value, error)) + logger.error("Error during request {} processing: {}".format(command, error)) else: - self._send_response(requested_value, request_id, value, filetransfer) + self._send_response(command, request_id, value) def _process_response(self, message): - request_id, requested_value = message.jsonheader["request_id"], message.jsonheader["requested_value"] + request_id, requested_value = message.content["request_id"], message.content["requested_value"] with self._request_lock: request = self._request_queue.pop(request_id, None) - if (request is None) or (request.requested_value != requested_value): - logger.warning("Unexpected response!") - return - if requested_value == "filetransfer": - value = True - self._process_filetransfer(message.content, request.callback_kwargs["filepath"]) - logger.debug( - "Request {} successfully closed with file bytes {}...".format(request, message.content[:256]) - ) - else: + if (request is not None) and (request.requested_value == requested_value): value = message.content["value"] logger.debug( "Request {} successfully closed with value {}".format(request, message.content["value"]) ) - if request.callback is not None: + print(self, "CALLBACK", request.callback, "VAL", value, "ARGS",request.callback_args, request.callback_kwargs) try: request.callback(self, value, *request.callback_args, **request.callback_kwargs) - except Exception as error: - logger.error("Error during response {} processing: {}".format(request, error)) - else: - logger.info("No callback were registered for response: {}".format(request)) + print(1) + except Exception as e: + logging.error("Error during callback call of request") # TODO more info + traceback.print_exc() + print(e) - @staticmethod - def _read_file(filepath): - with open(filepath, mode='rb') as f: - return f.read() - - def _process_filetransfer(self, content, filepath): - try: - with open(filepath, 'wb') as f: - f.write(content) - except OSError as error: - logger.error("File {} can not be written due error: {}".format(filepath, error)) else: - logger.info("File {} successfully received ".format(filepath)) - if self.whoami == "pi": - logger.info("Return rights to pi:pi after file transfer") - os.system("chown pi:pi {}".format(filepath)) + logger.warning("Unexpected response!") + + def _process_filetransfer(self, message): # TODO path? + if message.jsonheader["content-type"] == "binary": + filepath = message.jsonheader["filepath"] + try: + with open(filepath, 'wb') as f: + f.write(message.content) + except OSError as error: + logger.error("File {} can not be written due error: {}".format(filepath, error)) + else: + logger.info("File {} successfully received ".format(filepath)) + if self.whoami == "pi": + logger.info("Return rights to pi:pi after file transfer") + os.system("chown pi:pi {}".format(filepath)) def write(self): with self._send_lock: @@ -480,15 +453,14 @@ class ConnectionManager(object): self._set_selector_events_mask('rw') NotifierSock().notify() - def get_response(self, requested_value, callback, # timeout=30, - request_args=(), request_kwargs=None, - callback_args=(), callback_kwargs=None, ): - if request_kwargs is None: - request_kwargs = {} + def get_response(self, requested_value, callback, request_args=None, # timeout=30, + callback_args=(), callback_kwargs=None): + if request_args is None: + request_args = {} if callback_kwargs is None: callback_kwargs = {} - request_id = str(random.randint(0, 9999)).zfill(4) # maybe hash + request_id = str(random.randint(0, 9999)).zfill(4) with self._request_lock: self._request_queue[request_id] = PendingRequest( requested_value=requested_value, @@ -498,39 +470,24 @@ class ConnectionManager(object): callback_args=callback_args, callback_kwargs=callback_kwargs, request_args=request_args, - request_kwargs=request_kwargs, resend=True, ) - self._send(MessageManager.create_request(requested_value, request_id, request_args, request_kwargs)) - - def get_file(self, client_filepath, filepath=None, callback=None, - callback_args=(), callback_kwargs=None, ): - if callback_kwargs is None: - callback_kwargs = {} - - if filepath is None: - filepath = os.path.split(client_filepath)[1] - - request_kwargs = {"filepath": client_filepath} - callback_kwargs.update({"filepath": filepath}) - - self.get_response("filetransfer", callback, request_kwargs=request_kwargs, - callback_args=callback_args, callback_kwargs=callback_kwargs) + self._send(MessageManager.create_request(requested_value, request_id, request_args)) def _resend_requests(self): with self._request_lock: - for request_id, request in self._request_queue.items(): # TODO filter + for request_id, request in self._request_queue.items(): #TODO filter if request.resend: self._send(MessageManager.create_request( - request.requested_value, request_id, request.request_kwargs.update(resend=request.resend)) + request.requested_value, request_id, request.request_args.update(resend=request.resend)) ) request.resend = False - def send_message(self, action, args=(), kwargs=None): - self._send(MessageManager.create_action_message(action, args, kwargs)) + def send_message(self, command, args=None): + self._send(MessageManager.create_simple_message(command, args)) - def _send_response(self, requested_value, request_id, value, filetransfer=False): - self._send(MessageManager.create_response(requested_value, request_id, value, filetransfer)) + def _send_response(self, requested_value, request_id, value): + self._send(MessageManager.create_response(requested_value, request_id, value)) def send_file(self, filepath, dest_filepath): # clever_restart=False try: @@ -540,8 +497,9 @@ class ConnectionManager(object): logger.warning("File can not be opened due error: ".format(error)) else: logger.info("Sending file {} to {} (as: {})".format(filepath, self.addr, dest_filepath)) - self._send(MessageManager.create_message(data, "binary", "message", - additional_headers={"action": "filetransfer", "filepath": dest_filepath})) + self._send(MessageManager.create_message( + data, "binary", "filetransfer", "binary", {"filepath": dest_filepath} + )) class NotifierSock(Singleton):