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…
Reference in New Issue