mirror of
https://github.com/CopterExpress/clever-show.git
synced 2026-05-26 23:19:33 +00:00
Revert "Merge branch 'qt-gui-update' of https://github.com/CopterExpress/clever-show into qt-gui-update"
This reverts commita6c4bd76f4, reversing changes made tod0eed91f73.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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__':
|
||||
|
||||
@@ -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):
|
||||
|
||||
198
messaging_lib.py
198
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):
|
||||
|
||||
Reference in New Issue
Block a user