From c1b5b776d70d5baae674659a23f38344c486fb7a Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Mon, 30 Oct 2023 00:32:52 +0100 Subject: [PATCH] Implemented telemetry requests --- sbapp/main.py | 36 ++++++++++++++++++-- sbapp/sideband/core.py | 70 +++++++++++++++++++++++++++++++++++++-- sbapp/sideband/sense.py | 3 ++ sbapp/ui/objectdetails.py | 42 +++++++++++++++++------ 4 files changed, 135 insertions(+), 16 deletions(-) diff --git a/sbapp/main.py b/sbapp/main.py index b4e2eda..8104260 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -3185,11 +3185,41 @@ class SidebandApp(MDApp): self.telemetry_info_dialog.title = title_str self.telemetry_info_dialog.text = info_str self.telemetry_info_dialog.open() - pass def telemetry_request_action(self, sender=None): - self.sideband.request_latest_telemetry(from_addr=self.sideband.config["telemetry_collector"]) - pass + if not hasattr(self, "telemetry_info_dialog") or self.telemetry_info_dialog == None: + ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) + self.telemetry_info_dialog = MDDialog( + title="Info", + text="", + buttons=[ ok_button ], + ) + + def dl_ok(s): + self.telemetry_info_dialog.dismiss() + ok_button.bind(on_release=dl_ok) + + result = self.sideband.request_latest_telemetry(from_addr=self.sideband.config["telemetry_collector"]) + + if result == "destination_unknown": + title_str = "Unknown Destination" + info_str = "No keys known for the destination. Connected reticules have been queried for the keys." + elif result == "in_progress": + title_str = "Transfer In Progress" + info_str = "There is already a telemetry request transfer in progress for this peer." + elif result == "sent": + title_str = "Request Sent" + info_str = "A telemetry request was sent to the peer. The peer should send any available telemetry shortly." + elif result == "not_sent": + title_str = "Not Sent" + info_str = "A telemetry request could not be sent." + else: + title_str = "Unknown Status" + info_str = "The status of the telemetry request is unknown." + + self.telemetry_info_dialog.title = title_str + self.telemetry_info_dialog.text = info_str + self.telemetry_info_dialog.open() ### Map Screen ###################################### diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py index 4194703..6fd4a0e 100644 --- a/sbapp/sideband/core.py +++ b/sbapp/sideband/core.py @@ -14,7 +14,7 @@ import RNS.Interfaces.Interface as Interface import multiprocessing.connection from .res import sideband_fb_data -from .sense import Telemeter +from .sense import Telemeter, Commands if RNS.vendor.platformutils.get_platform() == "android": from jnius import autoclass, cast @@ -125,6 +125,7 @@ class SidebandCore(): self.pending_telemetry_send_maxtries = 2 self.telemetry_send_blocked_until = 0 self.pending_telemetry_request = False + self.telemetry_request_max_history = 3*24*60*60 self.state_db = {} self.rpc_connection = None @@ -883,8 +884,73 @@ class SidebandCore(): self.setstate(f"telemetry.{RNS.hexrep(message.destination_hash, delimit=False)}.update_sending", False) + def telemetry_request_finished(self, message): + if message.state == LXMF.LXMessage.FAILED and hasattr(message, "try_propagation_on_fail") and message.try_propagation_on_fail: + RNS.log("Direct delivery of telemetry request "+str(message)+" failed. Retrying as propagated message.", RNS.LOG_VERBOSE) + message.try_propagation_on_fail = None + message.delivery_attempts = 0 + del message.next_delivery_attempt + message.packed = None + message.desired_method = LXMF.LXMessage.PROPAGATED + self.message_router.handle_outbound(message) + else: + if message.state == LXMF.LXMessage.DELIVERED: + self.setpersistent(f"telemetry.{RNS.hexrep(message.destination_hash, delimit=False)}.last_request_success_timebase", message.request_timebase) + self.setstate(f"telemetry.{RNS.hexrep(message.destination_hash, delimit=False)}.request_sending", False) + if message.destination_hash == self.config["telemetry_collector"]: + self.pending_telemetry_request = False + self.pending_telemetry_request_try = 0 + self.telemetry_request_blocked_until = 0 + else: + self.setstate(f"telemetry.{RNS.hexrep(message.destination_hash, delimit=False)}.request_sending", False) + + def request_latest_telemetry(self, from_addr=None): - pass + if self.getstate(f"telemetry.{RNS.hexrep(from_addr, delimit=False)}.request_sending") == True: + RNS.log("Not sending new telemetry request, since an earlier transfer is already in progress", RNS.LOG_DEBUG) + return "in_progress" + + if from_addr != None: + dest_identity = RNS.Identity.recall(from_addr) + + if dest_identity == None: + RNS.log("The identity for "+RNS.prettyhexrep(from_addr)+" could not be recalled. Requesting identity from network...", RNS.LOG_DEBUG) + RNS.Transport.request_path(from_addr) + return "destination_unknown" + + else: + now = time.time() + dest = RNS.Destination(dest_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "lxmf", "delivery") + source = self.lxmf_destination + + if self.config["telemetry_use_propagation_only"] == True: + desired_method = LXMF.LXMessage.PROPAGATED + else: + desired_method = LXMF.LXMessage.DIRECT + + request_timebase = self.getpersistent(f"telemetry.{RNS.hexrep(from_addr, delimit=False)}.timebase") or now - self.telemetry_request_max_history + lxm_fields = { LXMF.FIELD_COMMANDS: [ + {Commands.TELEMETRY_REQUEST: request_timebase}, + ]} + + lxm = LXMF.LXMessage(dest, source, "", desired_method=desired_method, fields = lxm_fields) + lxm.request_timebase = request_timebase + lxm.register_delivery_callback(self.telemetry_request_finished) + lxm.register_failed_callback(self.telemetry_request_finished) + + if self.message_router.get_outbound_propagation_node() != None: + if self.config["telemetry_try_propagation_on_fail"]: + lxm.try_propagation_on_fail = True + + RNS.log(f"Sending telemetry request with timebase {request_timebase}", RNS.LOG_DEBUG) + self.setpersistent(f"telemetry.{RNS.hexrep(from_addr, delimit=False)}.last_request_attempt", time.time()) + self.setstate(f"telemetry.{RNS.hexrep(from_addr, delimit=False)}.request_sending", True) + self.message_router.handle_outbound(lxm) + return "sent" + + else: + return "not_sent" + def send_latest_telemetry(self, to_addr=None): if self.getstate(f"telemetry.{RNS.hexrep(to_addr, delimit=False)}.update_sending") == True: diff --git a/sbapp/sideband/sense.py b/sbapp/sideband/sense.py index 2c1ff09..431c919 100644 --- a/sbapp/sideband/sense.py +++ b/sbapp/sideband/sense.py @@ -8,6 +8,9 @@ from RNS.vendor import umsgpack as umsgpack from .geo import orthodromic_distance, euclidian_distance from .geo import azalt, angle_to_horizon, radio_horizon, shared_radio_horizon +class Commands(): + TELEMETRY_REQUEST = 0x01 + class Telemeter(): @staticmethod def from_packed(packed): diff --git a/sbapp/ui/objectdetails.py b/sbapp/ui/objectdetails.py index 70ea55e..3737503 100644 --- a/sbapp/ui/objectdetails.py +++ b/sbapp/ui/objectdetails.py @@ -226,6 +226,26 @@ class ObjectDetails(): if not self.viewing_self: result = self.app.sideband.request_latest_telemetry(from_addr=self.object_hash) + if result == "destination_unknown": + title_str = "Unknown Destination" + info_str = "No keys known for the destination. Connected reticules have been queried for the keys." + elif result == "in_progress": + title_str = "Transfer In Progress" + info_str = "There is already a telemetry request transfer in progress for this peer." + elif result == "sent": + title_str = "Request Sent" + info_str = "A telemetry request was sent to the peer. The peer should send any available telemetry shortly." + elif result == "not_sent": + title_str = "Not Sent" + info_str = "A telemetry request could not be sent." + else: + title_str = "Unknown Status" + info_str = "The status of the telemetry request is unknown." + + self.info_dialog.title = title_str + self.info_dialog.text = info_str + self.info_dialog.open() + def clear_widget(self): pass @@ -626,6 +646,17 @@ MDScreen: height: self.minimum_height padding: [dp(24), dp(24), dp(24), dp(24)] + MDRectangleFlatIconButton: + id: send_button + icon: "upload-lock" + text: "Send Update" + padding: [dp(0), dp(14), dp(0), dp(14)] + icon_size: dp(24) + font_size: dp(16) + size_hint: [1.0, None] + on_release: root.delegate.send_update() + disabled: False + MDRectangleFlatIconButton: id: request_button icon: "arrow-down-bold-hexagon-outline" @@ -637,17 +668,6 @@ MDScreen: on_release: root.delegate.request_update() disabled: False - MDRectangleFlatIconButton: - id: send_button - icon: "upload-lock" - text: "Send Update Now" - padding: [dp(0), dp(14), dp(0), dp(14)] - icon_size: dp(24) - font_size: dp(16) - size_hint: [1.0, None] - on_release: root.delegate.send_update() - disabled: False - # MDBoxLayout: # orientation: "horizontal" # spacing: dp(16)