mirror of
				https://github.com/liberatedsystems/openCom-Companion.git
				synced 2025-07-08 05:07:21 +02:00 
			
		
		
		
	Implemented object details view
This commit is contained in:
		
							parent
							
								
									3b0f75e9bc
								
							
						
					
					
						commit
						8fee0bae58
					
				@ -723,6 +723,8 @@ class SidebandApp(MDApp):
 | 
			
		||||
        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "w"):
 | 
			
		||||
            if self.root.ids.screen_manager.current == "conversations_screen":
 | 
			
		||||
                self.quit_action(self)
 | 
			
		||||
            elif self.root.ids.screen_manager.current == "object_details_screen":
 | 
			
		||||
                self.object_details_screen.close_action()
 | 
			
		||||
            else:
 | 
			
		||||
                self.open_conversations(direction="right")
 | 
			
		||||
        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "s" or text == "d"):
 | 
			
		||||
@ -759,6 +761,8 @@ class SidebandApp(MDApp):
 | 
			
		||||
                    self.close_sub_hardware_action()
 | 
			
		||||
                elif self.root.ids.screen_manager.current == "hardware_serial_screen":
 | 
			
		||||
                    self.close_sub_hardware_action()
 | 
			
		||||
                if self.root.ids.screen_manager.current == "object_details_screen":
 | 
			
		||||
                    self.object_details_screen.close_action()
 | 
			
		||||
                else:
 | 
			
		||||
                    self.open_conversations(direction="right")
 | 
			
		||||
 | 
			
		||||
@ -847,14 +851,14 @@ class SidebandApp(MDApp):
 | 
			
		||||
        Clock.schedule_once(cb, 0.15)
 | 
			
		||||
        Clock.schedule_once(cbu, 0.15+0.25)
 | 
			
		||||
 | 
			
		||||
    def open_conversation(self, context_dest):
 | 
			
		||||
    def open_conversation(self, context_dest, direction="left"):
 | 
			
		||||
        self.outbound_mode_paper = False
 | 
			
		||||
        if self.sideband.config["propagation_by_default"]:
 | 
			
		||||
            self.outbound_mode_propagation = True
 | 
			
		||||
        else:
 | 
			
		||||
            self.outbound_mode_propagation = False
 | 
			
		||||
 | 
			
		||||
        self.root.ids.screen_manager.transition.direction = "left"
 | 
			
		||||
        self.root.ids.screen_manager.transition.direction = direction
 | 
			
		||||
        self.messages_view = Messages(self, context_dest)
 | 
			
		||||
 | 
			
		||||
        self.messages_view.ids.messages_scrollview.effect_cls = ScrollEffect
 | 
			
		||||
@ -952,6 +956,10 @@ class SidebandApp(MDApp):
 | 
			
		||||
            context_dest = self.messages_view.ids.messages_scrollview.active_conversation
 | 
			
		||||
            self.map_show_peer_location(context_dest)
 | 
			
		||||
 | 
			
		||||
    def peer_show_telemetry_action(self, sender):
 | 
			
		||||
        if self.root.ids.screen_manager.current == "messages_screen":
 | 
			
		||||
            self.object_details_action(self.messages_view, from_conv=True)
 | 
			
		||||
 | 
			
		||||
    def message_propagation_action(self, sender):
 | 
			
		||||
        if self.outbound_mode_paper:
 | 
			
		||||
            self.outbound_mode_paper = False
 | 
			
		||||
@ -1248,10 +1256,7 @@ class SidebandApp(MDApp):
 | 
			
		||||
            def lj():
 | 
			
		||||
                import webbrowser
 | 
			
		||||
                webbrowser.open("https://unsigned.io/donate")
 | 
			
		||||
            if not RNS.vendor.platformutils.is_android():
 | 
			
		||||
                threading.Thread(target=lj, daemon=True).start()
 | 
			
		||||
            else:
 | 
			
		||||
                lj()
 | 
			
		||||
            threading.Thread(target=lj, daemon=True).start()
 | 
			
		||||
 | 
			
		||||
        self.information_screen.ids.information_scrollview.effect_cls = ScrollEffect
 | 
			
		||||
        self.information_screen.ids.information_logo.icon = self.sideband.asset_dir+"/rns_256.png"
 | 
			
		||||
@ -2935,6 +2940,17 @@ class SidebandApp(MDApp):
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_location.active = self.sideband.config["telemetry_s_location"]
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_location.bind(active=self.telemetry_location_toggle)
 | 
			
		||||
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_location.active = self.sideband.config["telemetry_s_fixed_location"]
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_location.bind(active=self.telemetry_location_toggle)
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_latlon.bind(focus=self.telemetry_save)
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_altitude.bind(focus=self.telemetry_save)
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_altitude.text = str(self.sideband.config["telemetry_s_fixed_altitude"])
 | 
			
		||||
            try:
 | 
			
		||||
                lat = self.sideband.config["telemetry_s_fixed_latlon"][0]; lon = self.sideband.config["telemetry_s_fixed_latlon"][1]
 | 
			
		||||
            except:
 | 
			
		||||
                lat = 0.0; lon = 0.0
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}"
 | 
			
		||||
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_battery.active = self.sideband.config["telemetry_s_battery"]
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_battery.bind(active=self.telemetry_save)
 | 
			
		||||
            
 | 
			
		||||
@ -2986,6 +3002,14 @@ class SidebandApp(MDApp):
 | 
			
		||||
            self.sideband.stop_telemetry()
 | 
			
		||||
    
 | 
			
		||||
    def telemetry_location_toggle(self, sender=None, event=None):
 | 
			
		||||
        if sender == self.telemetry_screen.ids.telemetry_s_location:
 | 
			
		||||
            if self.telemetry_screen.ids.telemetry_s_location.active:
 | 
			
		||||
                self.telemetry_screen.ids.telemetry_s_fixed_location.active = False
 | 
			
		||||
        if sender == self.telemetry_screen.ids.telemetry_s_fixed_location:
 | 
			
		||||
            if self.telemetry_screen.ids.telemetry_s_fixed_location.active:
 | 
			
		||||
                self.telemetry_screen.ids.telemetry_s_location.active = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if self.telemetry_screen.ids.telemetry_s_location.active:
 | 
			
		||||
            if RNS.vendor.platformutils.is_android():
 | 
			
		||||
                if not check_permission("android.permission.ACCESS_COARSE_LOCATION") or not check_permission("android.permission.ACCESS_FINE_LOCATION"):
 | 
			
		||||
@ -3012,6 +3036,7 @@ class SidebandApp(MDApp):
 | 
			
		||||
        self.sideband.config["telemetry_send_appearance"] = self.telemetry_screen.ids.telemetry_send_appearance.active
 | 
			
		||||
        
 | 
			
		||||
        self.sideband.config["telemetry_s_location"] = self.telemetry_screen.ids.telemetry_s_location.active
 | 
			
		||||
        self.sideband.config["telemetry_s_fixed_location"] = self.telemetry_screen.ids.telemetry_s_fixed_location.active
 | 
			
		||||
        self.sideband.config["telemetry_s_battery"] = self.telemetry_screen.ids.telemetry_s_battery.active
 | 
			
		||||
        self.sideband.config["telemetry_s_pressure"] = self.telemetry_screen.ids.telemetry_s_barometer.active
 | 
			
		||||
        self.sideband.config["telemetry_s_temperature"] = self.telemetry_screen.ids.telemetry_s_temperature.active
 | 
			
		||||
@ -3022,6 +3047,28 @@ class SidebandApp(MDApp):
 | 
			
		||||
        self.sideband.config["telemetry_s_angular_velocity"] = self.telemetry_screen.ids.telemetry_s_gyroscope.active
 | 
			
		||||
        self.sideband.config["telemetry_s_acceleration"] = self.telemetry_screen.ids.telemetry_s_accelerometer.active
 | 
			
		||||
        self.sideband.config["telemetry_s_proximity"] = self.telemetry_screen.ids.telemetry_s_proximity.active
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            alt = float(self.telemetry_screen.ids.telemetry_s_fixed_altitude.text.strip().replace(" ", ""))
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_altitude.text = str(alt)
 | 
			
		||||
            self.sideband.config["telemetry_s_fixed_altitude"] = alt
 | 
			
		||||
        except:
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_altitude.text = str(self.sideband.config["telemetry_s_fixed_altitude"])
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            s = self.telemetry_screen.ids.telemetry_s_fixed_latlon.text
 | 
			
		||||
            l = s.strip().replace(" ","").split(",")
 | 
			
		||||
            lat = float(l[0]); lon = float(l[1])
 | 
			
		||||
            self.sideband.config["telemetry_s_fixed_latlon"] = [lat, lon]
 | 
			
		||||
            self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}"
 | 
			
		||||
        except:
 | 
			
		||||
            try:
 | 
			
		||||
                lat = self.sideband.config["telemetry_s_fixed_latlon"][0]
 | 
			
		||||
                lon = self.sideband.config["telemetry_s_fixed_latlon"][1]
 | 
			
		||||
                self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}"
 | 
			
		||||
            except:
 | 
			
		||||
                self.sideband.config["telemetry_s_fixed_latlon"] = [0.0, 0.0]
 | 
			
		||||
                self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = "0.0, 0.0"
 | 
			
		||||
        
 | 
			
		||||
        self.sideband.save_configuration()
 | 
			
		||||
        self.sideband.setstate("app.flags.last_telemetry", time.time())
 | 
			
		||||
@ -3205,22 +3252,24 @@ class SidebandApp(MDApp):
 | 
			
		||||
            self.map_action()
 | 
			
		||||
            self.map_show(location)
 | 
			
		||||
 | 
			
		||||
    def map_display_telemetry(self, sender):
 | 
			
		||||
        RNS.log("Display telemetry from "+str(sender), RNS.LOG_WARNING)
 | 
			
		||||
        self.object_details_action()
 | 
			
		||||
    def map_display_telemetry(self, sender=None):
 | 
			
		||||
        self.object_details_action(sender)
 | 
			
		||||
 | 
			
		||||
    def close_sub_map_action(self, sender=None):
 | 
			
		||||
        self.map_action(direction="right")
 | 
			
		||||
 | 
			
		||||
    def object_details_action(self, sender=None):
 | 
			
		||||
    def object_details_action(self, sender=None, from_conv=False):
 | 
			
		||||
        self.root.ids.screen_manager.transition.direction = "left"
 | 
			
		||||
        self.root.ids.nav_drawer.set_state("closed")
 | 
			
		||||
        
 | 
			
		||||
        if self.object_details_screen == None:
 | 
			
		||||
            self.object_details_screen = ObjectDetails(self)
 | 
			
		||||
 | 
			
		||||
        self.root.ids.screen_manager.current = "object_details_screen"
 | 
			
		||||
        self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
 | 
			
		||||
        if sender != None and hasattr(sender, "source_dest") and sender.source_dest != None:
 | 
			
		||||
            if self.object_details_screen == None:
 | 
			
		||||
                self.object_details_screen = ObjectDetails(self)
 | 
			
		||||
 | 
			
		||||
            self.object_details_screen.set_source(sender.source_dest, from_conv=from_conv)
 | 
			
		||||
 | 
			
		||||
            self.root.ids.screen_manager.current = "object_details_screen"
 | 
			
		||||
            self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
 | 
			
		||||
 | 
			
		||||
    def map_create_marker(self, source, telemetry, appearance):
 | 
			
		||||
        try:
 | 
			
		||||
@ -3228,6 +3277,7 @@ class SidebandApp(MDApp):
 | 
			
		||||
            a_icon = appearance[0]
 | 
			
		||||
            a_fg = appearance[1]; a_bg = appearance[2]
 | 
			
		||||
            marker = CustomMapMarker(lat=l["latitude"], lon=l["longtitude"], icon_bg=a_bg)
 | 
			
		||||
            marker.app = self
 | 
			
		||||
            marker.source_dest = source
 | 
			
		||||
            marker.location_time = l["last_update"]
 | 
			
		||||
            marker.icon = MDMapIconButton(
 | 
			
		||||
@ -3237,6 +3287,7 @@ class SidebandApp(MDApp):
 | 
			
		||||
                on_release=self.map_display_telemetry,
 | 
			
		||||
                )
 | 
			
		||||
            marker.icon._default_icon_pad = dp(16)
 | 
			
		||||
            marker.icon.source_dest = marker.source_dest
 | 
			
		||||
            marker.add_widget(marker.icon)
 | 
			
		||||
 | 
			
		||||
            ########
 | 
			
		||||
 | 
			
		||||
@ -472,6 +472,8 @@ class SidebandCore():
 | 
			
		||||
            self.config["telemetry_bg"] = SidebandCore.DEFAULT_APPEARANCE[2]
 | 
			
		||||
        if not "telemetry_send_appearance" in self.config:
 | 
			
		||||
            self.config["telemetry_send_appearance"] = False
 | 
			
		||||
        if not "telemetry_display_trusted_only" in self.config:
 | 
			
		||||
            self.config["telemetry_display_trusted_only"] = False
 | 
			
		||||
 | 
			
		||||
        if not "telemetry_s_location" in self.config:
 | 
			
		||||
            self.config["telemetry_s_location"] = False
 | 
			
		||||
@ -495,8 +497,12 @@ class SidebandCore():
 | 
			
		||||
            self.config["telemetry_s_acceleration"] = False
 | 
			
		||||
        if not "telemetry_s_proximity" in self.config:
 | 
			
		||||
            self.config["telemetry_s_proximity"] = False
 | 
			
		||||
        if not "telemetry_display_trusted_only" in self.config:
 | 
			
		||||
            self.config["telemetry_display_trusted_only"] = False
 | 
			
		||||
        if not "telemetry_s_fixed_location" in self.config:
 | 
			
		||||
            self.config["telemetry_s_fixed_location"] = False
 | 
			
		||||
        if not "telemetry_s_fixed_latlon" in self.config:
 | 
			
		||||
            self.config["telemetry_s_fixed_latlon"] = [0.0, 0.0]
 | 
			
		||||
        if not "telemetry_s_fixed_altitude" in self.config:
 | 
			
		||||
            self.config["telemetry_s_fixed_altitude"] = 0.0
 | 
			
		||||
 | 
			
		||||
        if not "map_history_limit" in self.config:
 | 
			
		||||
            self.config["map_history_limit"] = 7*24*60*60
 | 
			
		||||
@ -671,6 +677,8 @@ class SidebandCore():
 | 
			
		||||
        return self._db_get_appearance(context_dest) or SidebandCore.DEFAULT_APPEARANCE
 | 
			
		||||
 | 
			
		||||
    def peer_display_name(self, context_dest):
 | 
			
		||||
        if context_dest == self.lxmf_destination.hash:
 | 
			
		||||
            return self.config["display_name"]
 | 
			
		||||
        try:
 | 
			
		||||
            existing_conv = self._db_conversation(context_dest)
 | 
			
		||||
            if existing_conv != None:
 | 
			
		||||
@ -753,10 +761,20 @@ class SidebandCore():
 | 
			
		||||
        return self._db_telemetry(context_dest = context_dest, after = after, before = before, limit = limit) or []
 | 
			
		||||
 | 
			
		||||
    def peer_telemetry(self, context_dest, after = None, before = None, limit = None):
 | 
			
		||||
        pts = self._db_telemetry(context_dest, after = after, before = before, limit = limit)
 | 
			
		||||
        if pts != None:
 | 
			
		||||
            if context_dest in pts:
 | 
			
		||||
                return pts[context_dest]
 | 
			
		||||
        if context_dest == self.lxmf_destination.hash and limit == 1:
 | 
			
		||||
            try:
 | 
			
		||||
                return [[self.latest_telemetry["time"]["utc"], self.latest_packed_telemetry]]
 | 
			
		||||
            except:
 | 
			
		||||
                RNS.log("An error occurred while retrieving telemetry from the database: "+str(e), RNS.LOG_ERROR)
 | 
			
		||||
                return []
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            pts = self._db_telemetry(context_dest, after = after, before = before, limit = limit)
 | 
			
		||||
            if pts != None:
 | 
			
		||||
                if context_dest in pts:
 | 
			
		||||
                    return pts[context_dest]
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            RNS.log("An error occurred while retrieving telemetry from the database: "+str(e), RNS.LOG_ERROR)
 | 
			
		||||
 | 
			
		||||
        return []
 | 
			
		||||
 | 
			
		||||
@ -1142,8 +1160,10 @@ class SidebandCore():
 | 
			
		||||
        dbc = db.cursor()
 | 
			
		||||
 | 
			
		||||
        # TODO: Implement limit
 | 
			
		||||
 | 
			
		||||
        order_part = " order by ts DESC"
 | 
			
		||||
        limit_part = ""
 | 
			
		||||
        if limit:
 | 
			
		||||
            limit_part = " LIMIT "+str(int(limit))
 | 
			
		||||
        order_part = " order by ts DESC"+limit_part
 | 
			
		||||
        if context_dest == None:
 | 
			
		||||
            if after != None and before == None:
 | 
			
		||||
                query = "select * from telemetry where ts>:after_ts"+order_part
 | 
			
		||||
@ -1211,6 +1231,7 @@ class SidebandCore():
 | 
			
		||||
                if "snr" in physical_link: remote_telemeter.sensors["physical_link"].snr = physical_link["snr"]
 | 
			
		||||
                if "q" in physical_link: remote_telemeter.sensors["physical_link"].q = physical_link["q"]
 | 
			
		||||
                remote_telemeter.sensors["physical_link"].update_data()
 | 
			
		||||
                telemetry = remote_telemeter.packed()
 | 
			
		||||
            
 | 
			
		||||
            query = "INSERT INTO telemetry (dest_context, ts, data) values (?, ?, ?)"
 | 
			
		||||
            data = (context_dest, telemetry_timestamp, telemetry)
 | 
			
		||||
@ -1245,22 +1266,26 @@ class SidebandCore():
 | 
			
		||||
            db.commit()
 | 
			
		||||
 | 
			
		||||
    def _db_get_appearance(self, context_dest):
 | 
			
		||||
        conv = self._db_conversation(context_dest)
 | 
			
		||||
        data_dict = conv["data"]
 | 
			
		||||
        try:
 | 
			
		||||
            if data_dict != None and "appearance" in data_dict:
 | 
			
		||||
                def htf(cbytes):
 | 
			
		||||
                    d = 1.0/255.0
 | 
			
		||||
                    r = round(struct.unpack("!B", bytes([cbytes[0]]))[0]*d, 4)
 | 
			
		||||
                    g = round(struct.unpack("!B", bytes([cbytes[1]]))[0]*d, 4)
 | 
			
		||||
                    b = round(struct.unpack("!B", bytes([cbytes[2]]))[0]*d, 4)
 | 
			
		||||
                    return [r,g,b]
 | 
			
		||||
        if context_dest == self.lxmf_destination.hash:
 | 
			
		||||
            return [self.config["telemetry_icon"], self.config["telemetry_fg"], self.config["telemetry_bg"]]
 | 
			
		||||
        else:
 | 
			
		||||
            conv = self._db_conversation(context_dest)
 | 
			
		||||
            if conv != None and "data" in conv:
 | 
			
		||||
                data_dict = conv["data"]
 | 
			
		||||
                try:
 | 
			
		||||
                    if data_dict != None and "appearance" in data_dict:
 | 
			
		||||
                        def htf(cbytes):
 | 
			
		||||
                            d = 1.0/255.0
 | 
			
		||||
                            r = round(struct.unpack("!B", bytes([cbytes[0]]))[0]*d, 4)
 | 
			
		||||
                            g = round(struct.unpack("!B", bytes([cbytes[1]]))[0]*d, 4)
 | 
			
		||||
                            b = round(struct.unpack("!B", bytes([cbytes[2]]))[0]*d, 4)
 | 
			
		||||
                            return [r,g,b]
 | 
			
		||||
 | 
			
		||||
                appearance = [data_dict["appearance"][0], htf(data_dict["appearance"][1]), htf(data_dict["appearance"][2])]
 | 
			
		||||
                
 | 
			
		||||
                return appearance
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            RNS.log("Could not retrieve appearance for "+RNS.prettyhexrep(context_dest)+": "+str(e), RNS.LOG_ERROR)
 | 
			
		||||
                        appearance = [data_dict["appearance"][0], htf(data_dict["appearance"][1]), htf(data_dict["appearance"][2])]
 | 
			
		||||
                        
 | 
			
		||||
                        return appearance
 | 
			
		||||
                except Exception as e:
 | 
			
		||||
                    RNS.log("Could not retrieve appearance for "+RNS.prettyhexrep(context_dest)+": "+str(e), RNS.LOG_ERROR)
 | 
			
		||||
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
@ -1744,6 +1769,13 @@ class SidebandCore():
 | 
			
		||||
                    self.telemeter.enable(sensor)
 | 
			
		||||
                else:
 | 
			
		||||
                    self.telemeter.disable(sensor)
 | 
			
		||||
            
 | 
			
		||||
            if self.config["telemetry_s_fixed_location"]:
 | 
			
		||||
                self.telemeter.synthesize("location")
 | 
			
		||||
                self.telemeter.sensors["location"].latitude = self.config["telemetry_s_fixed_latlon"][0]
 | 
			
		||||
                self.telemeter.sensors["location"].longtitude = self.config["telemetry_s_fixed_latlon"][1]
 | 
			
		||||
                self.telemeter.sensors["location"].altitude = self.config["telemetry_s_fixed_altitude"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_telemetry(self):
 | 
			
		||||
        if self.config["telemetry_enabled"] == True:
 | 
			
		||||
 | 
			
		||||
@ -868,6 +868,7 @@ MDScreen:
 | 
			
		||||
                [
 | 
			
		||||
                ['arrow-down-bold-hexagon-outline', lambda x: root.app.telemetry_request_action(self)],
 | 
			
		||||
                ['upload-lock', lambda x: root.app.telemetry_send_update(self)],
 | 
			
		||||
                ['wrench-cog', lambda x: root.app.close_any_action(self)],
 | 
			
		||||
                ['close', lambda x: root.app.close_any_action(self)],
 | 
			
		||||
                ]
 | 
			
		||||
 | 
			
		||||
@ -1323,6 +1324,44 @@ MDScreen:
 | 
			
		||||
                        pos_hint: {"center_y": 0.3}
 | 
			
		||||
                        active: False
 | 
			
		||||
 | 
			
		||||
                MDBoxLayout:
 | 
			
		||||
                    orientation: "horizontal"
 | 
			
		||||
                    size_hint_y: None
 | 
			
		||||
                    padding: [0,0,dp(24),dp(0)]
 | 
			
		||||
                    height: dp(48)
 | 
			
		||||
                    
 | 
			
		||||
                    MDLabel:
 | 
			
		||||
                        text: "Fixed Location"
 | 
			
		||||
                        font_style: "H6"
 | 
			
		||||
 | 
			
		||||
                    MDSwitch:
 | 
			
		||||
                        id: telemetry_s_fixed_location
 | 
			
		||||
                        pos_hint: {"center_y": 0.3}
 | 
			
		||||
                        active: False
 | 
			
		||||
 | 
			
		||||
                MDBoxLayout:
 | 
			
		||||
                    id: telemetry_fixed_location_fields
 | 
			
		||||
                    orientation: "horizontal"
 | 
			
		||||
                    size_hint_y: None
 | 
			
		||||
                    spacing: dp(16)
 | 
			
		||||
                    height: dp(64)
 | 
			
		||||
                    padding: [0, dp(0), 0, dp(0)]
 | 
			
		||||
                    # md_bg_color: [1,0,0,1]
 | 
			
		||||
 | 
			
		||||
                    MDTextField:
 | 
			
		||||
                        id: telemetry_s_fixed_latlon
 | 
			
		||||
                        size_hint: [0.618, None]
 | 
			
		||||
                        hint_text: "Latitude, longtitude"
 | 
			
		||||
                        text: ""
 | 
			
		||||
                        font_size: dp(24)
 | 
			
		||||
 | 
			
		||||
                    MDTextField:
 | 
			
		||||
                        id: telemetry_s_fixed_altitude
 | 
			
		||||
                        size_hint: [0.382, None]
 | 
			
		||||
                        hint_text: "Altitude"
 | 
			
		||||
                        text: ""
 | 
			
		||||
                        font_size: dp(24)
 | 
			
		||||
 | 
			
		||||
                MDLabel:
 | 
			
		||||
                    markup: True
 | 
			
		||||
                    text: "\\n"
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,7 @@ class Messages():
 | 
			
		||||
    def __init__(self, app, context_dest):
 | 
			
		||||
        self.app = app
 | 
			
		||||
        self.context_dest = context_dest
 | 
			
		||||
        self.source_dest = context_dest
 | 
			
		||||
 | 
			
		||||
        self.screen = self.app.root.ids.screen_manager.get_screen("messages_screen")
 | 
			
		||||
        self.ids = self.screen.ids
 | 
			
		||||
@ -302,9 +303,15 @@ class Messages():
 | 
			
		||||
                    def x():
 | 
			
		||||
                        try:
 | 
			
		||||
                            telemeter = Telemeter.from_packed(packed_telemetry)
 | 
			
		||||
                            tlm = telemeter.read_all()
 | 
			
		||||
                            if extra_telemetry and len(extra_telemetry) != 0:
 | 
			
		||||
                                tlm["physical_link"] = extra_telemetry
 | 
			
		||||
                                physical_link = extra_telemetry
 | 
			
		||||
                                telemeter.synthesize("physical_link")
 | 
			
		||||
                                if "rssi" in physical_link: telemeter.sensors["physical_link"].rssi = physical_link["rssi"]
 | 
			
		||||
                                if "snr" in physical_link: telemeter.sensors["physical_link"].snr = physical_link["snr"]
 | 
			
		||||
                                if "quality" in physical_link: telemeter.sensors["physical_link"].q = physical_link["quality"]
 | 
			
		||||
                                telemeter.sensors["physical_link"].update_data()
 | 
			
		||||
                            
 | 
			
		||||
                            tlm = telemeter.read_all()
 | 
			
		||||
                            Clipboard.copy(str(tlm))
 | 
			
		||||
                            item.dmenu.dismiss()
 | 
			
		||||
                        except Exception as e:
 | 
			
		||||
@ -598,6 +605,7 @@ MDScreen:
 | 
			
		||||
                [['menu', lambda x: root.app.nav_drawer.set_state("open")],]
 | 
			
		||||
            right_action_items:
 | 
			
		||||
                [
 | 
			
		||||
                ['map-marker-path', lambda x: root.app.peer_show_telemetry_action(self)],
 | 
			
		||||
                ['map-search', lambda x: root.app.peer_show_location_action(self)],
 | 
			
		||||
                ['lan-connect', lambda x: root.app.message_propagation_action(self)],
 | 
			
		||||
                ['close', lambda x: root.app.close_settings_action(self)],
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,17 @@ import RNS
 | 
			
		||||
 | 
			
		||||
from kivy.metrics import dp,sp
 | 
			
		||||
from kivy.lang.builder import Builder
 | 
			
		||||
from kivy.core.clipboard import Clipboard
 | 
			
		||||
from kivymd.uix.recycleview import MDRecycleView
 | 
			
		||||
from kivymd.uix.list import OneLineIconListItem
 | 
			
		||||
from kivy.properties import StringProperty, BooleanProperty
 | 
			
		||||
from kivy.effects.scroll import ScrollEffect
 | 
			
		||||
from sideband.sense import Telemeter
 | 
			
		||||
import threading
 | 
			
		||||
import webbrowser
 | 
			
		||||
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if RNS.vendor.platformutils.get_platform() == "android":
 | 
			
		||||
    from ui.helpers import ts_format
 | 
			
		||||
@ -14,13 +25,60 @@ class ObjectDetails():
 | 
			
		||||
        self.app = app
 | 
			
		||||
        self.widget = None
 | 
			
		||||
        self.object_hash = object_hash
 | 
			
		||||
        self.coords = None
 | 
			
		||||
        self.raw_telemetry = None
 | 
			
		||||
        self.from_conv = False
 | 
			
		||||
 | 
			
		||||
        if not self.app.root.ids.screen_manager.has_screen("object_details_screen"):
 | 
			
		||||
            self.screen = Builder.load_string(layou_object_details)
 | 
			
		||||
            self.screen.app = self.app
 | 
			
		||||
            self.screen.delegate = self
 | 
			
		||||
            self.ids = self.screen.ids
 | 
			
		||||
            self.app.root.ids.screen_manager.add_widget(self.screen)
 | 
			
		||||
 | 
			
		||||
            self.screen.ids.object_details_scrollview.effect_cls = ScrollEffect
 | 
			
		||||
            self.telemetry_list = RVDetails()
 | 
			
		||||
            self.telemetry_list.delegate = self
 | 
			
		||||
            self.telemetry_list.app = self.app
 | 
			
		||||
            self.screen.ids.object_details_scrollview.add_widget(self.telemetry_list)
 | 
			
		||||
 | 
			
		||||
    def close_action(self, sender=None):
 | 
			
		||||
        if self.from_conv:
 | 
			
		||||
            self.app.open_conversation(self.object_hash, direction="right")
 | 
			
		||||
        else:
 | 
			
		||||
            self.app.close_sub_map_action()
 | 
			
		||||
 | 
			
		||||
    def set_source(self, source_dest, from_conv=False):
 | 
			
		||||
        self.object_hash = source_dest
 | 
			
		||||
 | 
			
		||||
        if from_conv:
 | 
			
		||||
            self.from_conv = True
 | 
			
		||||
        else:
 | 
			
		||||
            self.from_conv = False
 | 
			
		||||
 | 
			
		||||
        self.coords = None
 | 
			
		||||
        self.telemetry_list.data = []
 | 
			
		||||
        appearance = self.app.sideband.peer_appearance(source_dest)
 | 
			
		||||
        self.screen.ids.name_label.text = self.app.sideband.peer_display_name(source_dest)
 | 
			
		||||
        self.screen.ids.coordinates_button.disabled = True
 | 
			
		||||
        self.screen.ids.object_appearance.icon = appearance[0]
 | 
			
		||||
        self.screen.ids.object_appearance.icon_color = appearance[1]
 | 
			
		||||
        self.screen.ids.object_appearance.md_bg_color = appearance[2]
 | 
			
		||||
 | 
			
		||||
        latest_telemetry = self.app.sideband.peer_telemetry(source_dest, limit=1)
 | 
			
		||||
        if latest_telemetry != None and len(latest_telemetry) > 0:
 | 
			
		||||
            telemeter = Telemeter.from_packed(latest_telemetry[0][1])
 | 
			
		||||
            self.raw_telemetry = telemeter.read_all()
 | 
			
		||||
 | 
			
		||||
            rendered_telemetry = telemeter.render()
 | 
			
		||||
            if "location" in telemeter.sensors:
 | 
			
		||||
                self.screen.ids.coordinates_button.disabled = False
 | 
			
		||||
            self.telemetry_list.update_source(rendered_telemetry)
 | 
			
		||||
            self.screen.ids.telemetry_button.disabled = False
 | 
			
		||||
        else:
 | 
			
		||||
            self.screen.ids.telemetry_button.disabled = True
 | 
			
		||||
            self.telemetry_list.update_source(None)
 | 
			
		||||
 | 
			
		||||
    def reload(self):
 | 
			
		||||
        self.clear_widget()
 | 
			
		||||
        self.update()
 | 
			
		||||
@ -40,7 +98,131 @@ class ObjectDetails():
 | 
			
		||||
    def get_widget(self):
 | 
			
		||||
        return self.widget
 | 
			
		||||
 | 
			
		||||
    def copy_coordinates(self, sender=None):
 | 
			
		||||
        Clipboard.copy(str(self.coords or "No data"))
 | 
			
		||||
 | 
			
		||||
    def copy_telemetry(self, sender=None):
 | 
			
		||||
        Clipboard.copy(str(self.raw_telemetry or "No data"))
 | 
			
		||||
 | 
			
		||||
class ODView(OneLineIconListItem):
 | 
			
		||||
    icon = StringProperty()
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
 | 
			
		||||
class RVDetails(MDRecycleView):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.data = []
 | 
			
		||||
 | 
			
		||||
    def update_source(self, rendered_telemetry=None):
 | 
			
		||||
        if not rendered_telemetry:
 | 
			
		||||
            rendered_telemetry = []
 | 
			
		||||
        
 | 
			
		||||
        sort = {
 | 
			
		||||
            "Physical Link": 10,
 | 
			
		||||
            "Location": 20,
 | 
			
		||||
            "Ambient Light": 30,
 | 
			
		||||
            "Ambient Temperature": 40,
 | 
			
		||||
            "Relative Humidity": 50,
 | 
			
		||||
            "Ambient Pressure": 60,
 | 
			
		||||
            "Battery": 70,
 | 
			
		||||
            "Timestamp": 80,    
 | 
			
		||||
        }
 | 
			
		||||
        self.entries = []
 | 
			
		||||
        rendered_telemetry.sort(key=lambda s: sort[s["name"]] if s["name"] in sort else 1000)
 | 
			
		||||
        for s in rendered_telemetry:
 | 
			
		||||
            extra_entries = []
 | 
			
		||||
            release_function = None
 | 
			
		||||
            name = s["name"]
 | 
			
		||||
            if name == "Timestamp":
 | 
			
		||||
                ts = s["values"]["UTC"]
 | 
			
		||||
                ts_str = datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
 | 
			
		||||
                formatted_values = f"Recorded: [b]{RNS.prettytime(time.time()-ts, compact=True)} ago[/b] ({ts_str})"
 | 
			
		||||
            elif name == "Battery":
 | 
			
		||||
                p = s["values"]["percent"]
 | 
			
		||||
                cs = s["values"]["_meta"]
 | 
			
		||||
                formatted_values = f"{name}: [b]{p}%[/b] ({cs})"
 | 
			
		||||
            elif name == "Ambient Pressure":
 | 
			
		||||
                p = s["values"]["mbar"]
 | 
			
		||||
                formatted_values = f"{name}: [b]{p} mbar[/b]"
 | 
			
		||||
            elif name == "Ambient Temperature":
 | 
			
		||||
                c = s["values"]["c"]
 | 
			
		||||
                formatted_values = f"{name}: [b]{c}° C[/b]"
 | 
			
		||||
            elif name == "Relative Humidity":
 | 
			
		||||
                r = s["values"]["percent"]
 | 
			
		||||
                formatted_values = f"{name}: [b]{r}%[/b]"
 | 
			
		||||
            elif name == "Physical Link":
 | 
			
		||||
                rssi = s["values"]["rssi"]
 | 
			
		||||
                snr = s["values"]["snr"]
 | 
			
		||||
                q = s["values"]["q"]
 | 
			
		||||
                formatted_values = f"Link Quality: [b]{q}%[/b], RSSI: [b]{rssi} dBm[/b], SNR: [b]{snr} dB[/b]"
 | 
			
		||||
            elif name == "Location":
 | 
			
		||||
                lat = s["values"]["latitude"]
 | 
			
		||||
                lon = s["values"]["longtitude"]
 | 
			
		||||
                alt = s["values"]["altitude"]
 | 
			
		||||
                speed = s["values"]["speed"]
 | 
			
		||||
                bearing = s["values"]["bearing"]
 | 
			
		||||
                accuracy = s["values"]["accuracy"]
 | 
			
		||||
                updated = s["values"]["updated"]
 | 
			
		||||
                updated_str = f", Logged: [b]{RNS.prettytime(time.time()-updated, compact=True)} ago[/b]"
 | 
			
		||||
                if speed > 0.01:
 | 
			
		||||
                    speed_str = ", Speed: [b]{speed} Km/h[/b]"
 | 
			
		||||
                else:
 | 
			
		||||
                    speed_str = ""
 | 
			
		||||
                coords = f"{lat}, {lon}"
 | 
			
		||||
                self.delegate.coords = coords
 | 
			
		||||
                formatted_values = f"Coordinates: [b]{coords}[/b], Altitude: [b]{alt} meters[/b]"+speed_str+f", Bearing: [b]{bearing}°[/b]"
 | 
			
		||||
                extra_formatted_values = f"Uncertainty: [b]{accuracy} meters[/b]"+updated_str
 | 
			
		||||
 | 
			
		||||
                data = {"icon": s["icon"], "text": f"{formatted_values}"}
 | 
			
		||||
                extra_entries.append({"icon": "map-marker-question", "text": extra_formatted_values})
 | 
			
		||||
                def select(e=None):
 | 
			
		||||
                    geo_uri = f"geo:{lat},{lon}"
 | 
			
		||||
                    def lj():
 | 
			
		||||
                        webbrowser.open(geo_uri)
 | 
			
		||||
                    threading.Thread(target=lj, daemon=True).start()
 | 
			
		||||
 | 
			
		||||
                release_function = select
 | 
			
		||||
            else:
 | 
			
		||||
                formatted_values = f"{name}:"
 | 
			
		||||
                for vn in s["values"]:
 | 
			
		||||
                    v = s["values"][vn]
 | 
			
		||||
                    formatted_values += f" [b]{v} {vn}[/b]"
 | 
			
		||||
            
 | 
			
		||||
            if release_function:
 | 
			
		||||
                data = {"icon": s["icon"], "text": f"{formatted_values}", "on_release": release_function}
 | 
			
		||||
            else:
 | 
			
		||||
                data = {"icon": s["icon"], "text": f"{formatted_values}"}
 | 
			
		||||
 | 
			
		||||
            self.entries.append(data)
 | 
			
		||||
            for extra in extra_entries:
 | 
			
		||||
                self.entries.append(extra)
 | 
			
		||||
 | 
			
		||||
        if len(self.entries) == 0:
 | 
			
		||||
            self.entries.append({"icon": "account-question-outline", "text": f"No information known about this peer"})
 | 
			
		||||
 | 
			
		||||
        self.data = self.entries
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layou_object_details = """
 | 
			
		||||
#:import MDLabel kivymd.uix.label.MDLabel
 | 
			
		||||
#:import OneLineIconListItem kivymd.uix.list.OneLineIconListItem
 | 
			
		||||
#:import Button kivy.uix.button.Button
 | 
			
		||||
 | 
			
		||||
<ODView>
 | 
			
		||||
    IconLeftWidget:
 | 
			
		||||
        icon: root.icon
 | 
			
		||||
 | 
			
		||||
<RVDetails>:
 | 
			
		||||
    viewclass: "ODView"
 | 
			
		||||
    RecycleBoxLayout:
 | 
			
		||||
        default_size: None, dp(50)
 | 
			
		||||
        default_size_hint: 1, None
 | 
			
		||||
        size_hint_y: None
 | 
			
		||||
        height: self.minimum_height
 | 
			
		||||
        orientation: "vertical"
 | 
			
		||||
 | 
			
		||||
MDScreen:
 | 
			
		||||
    name: "object_details_screen"
 | 
			
		||||
    
 | 
			
		||||
@ -48,6 +230,7 @@ MDScreen:
 | 
			
		||||
        orientation: "vertical"
 | 
			
		||||
 | 
			
		||||
        MDTopAppBar:
 | 
			
		||||
            id: details_bar
 | 
			
		||||
            title: "Details"
 | 
			
		||||
            anchor_title: "left"
 | 
			
		||||
            elevation: 0
 | 
			
		||||
@ -55,29 +238,62 @@ MDScreen:
 | 
			
		||||
                [['menu', lambda x: root.app.nav_drawer.set_state("open")]]
 | 
			
		||||
            right_action_items:
 | 
			
		||||
                [
 | 
			
		||||
                ['close', lambda x: root.app.close_sub_map_action(self)],
 | 
			
		||||
                ['close', lambda x: root.delegate.close_action()],
 | 
			
		||||
                ]
 | 
			
		||||
 | 
			
		||||
        MDBoxLayout:
 | 
			
		||||
            id: object_header
 | 
			
		||||
            orientation: "horizontal"
 | 
			
		||||
            spacing: dp(24)
 | 
			
		||||
            size_hint_y: None
 | 
			
		||||
            height: self.minimum_height
 | 
			
		||||
            padding: dp(24)
 | 
			
		||||
 | 
			
		||||
            MDIconButton:
 | 
			
		||||
                id: object_appearance
 | 
			
		||||
                icon: "map-marker-star-outline"
 | 
			
		||||
                icon_color: [0,0,0,1]
 | 
			
		||||
                md_bg_color: [1,1,1,1]
 | 
			
		||||
                theme_icon_color: "Custom"
 | 
			
		||||
                icon_size: dp(32)
 | 
			
		||||
 | 
			
		||||
            MDLabel:
 | 
			
		||||
                id: name_label
 | 
			
		||||
                markup: True
 | 
			
		||||
                text: "Object Name"
 | 
			
		||||
                font_style: "H6"
 | 
			
		||||
 | 
			
		||||
        MDBoxLayout:
 | 
			
		||||
            id: object_header
 | 
			
		||||
            orientation: "horizontal"
 | 
			
		||||
            spacing: dp(24)
 | 
			
		||||
            size_hint_y: None
 | 
			
		||||
            height: self.minimum_height
 | 
			
		||||
            padding: [dp(24), dp(0), dp(24), dp(12)]
 | 
			
		||||
 | 
			
		||||
            MDRectangleFlatIconButton:
 | 
			
		||||
                id: telemetry_button
 | 
			
		||||
                icon: "content-copy"
 | 
			
		||||
                text: "Copy Telemetry"
 | 
			
		||||
                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.copy_telemetry(self)
 | 
			
		||||
                disabled: False
 | 
			
		||||
 | 
			
		||||
            MDRectangleFlatIconButton:
 | 
			
		||||
                id: coordinates_button
 | 
			
		||||
                icon: "map-marker-outline"
 | 
			
		||||
                text: "Copy Coordinates"
 | 
			
		||||
                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.copy_coordinates(self)
 | 
			
		||||
                disabled: False
 | 
			
		||||
            
 | 
			
		||||
        ScrollView:
 | 
			
		||||
            id: object_details_scrollview
 | 
			
		||||
 | 
			
		||||
            MDBoxLayout:
 | 
			
		||||
                orientation: "vertical"
 | 
			
		||||
                spacing: dp(48)
 | 
			
		||||
                size_hint_y: None
 | 
			
		||||
                height: self.minimum_height
 | 
			
		||||
                padding: [dp(28), dp(48), dp(28), dp(16)]
 | 
			
		||||
 | 
			
		||||
                MDLabel:
 | 
			
		||||
                    id: name_label
 | 
			
		||||
                    markup: True
 | 
			
		||||
                    text: "Object Name"
 | 
			
		||||
                    font_style: "H6"
 | 
			
		||||
                
 | 
			
		||||
                MDLabel:
 | 
			
		||||
                    id: test_label
 | 
			
		||||
                    markup: True
 | 
			
		||||
                    text: "Test"
 | 
			
		||||
                    font_style: "H6"
 | 
			
		||||
                
 | 
			
		||||
"""
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user