Added telemetry system, location sharing and map view for shared locations
This commit is contained in:
parent
a9160b558b
commit
314499109c
276
sbapp/main.py
276
sbapp/main.py
|
@ -44,8 +44,9 @@ from kivy.uix.screenmanager import FadeTransition, NoTransition
|
|||
from kivymd.uix.list import OneLineIconListItem
|
||||
from kivy.properties import StringProperty
|
||||
from kivymd.uix.pickers import MDColorPicker
|
||||
from kivymd.uix.button import BaseButton, MDIconButton
|
||||
from sideband.sense import Telemeter
|
||||
from mapview import MapMarker
|
||||
from mapview import CustomMapMarker
|
||||
|
||||
if RNS.vendor.platformutils.get_platform() == "android":
|
||||
from sideband.core import SidebandCore
|
||||
|
@ -922,6 +923,11 @@ class SidebandApp(MDApp):
|
|||
self.root.ids.message_send_button.disabled = False
|
||||
Clock.schedule_once(cb, 0.5)
|
||||
|
||||
def peer_show_location_action(self, sender):
|
||||
if self.root.ids.screen_manager.current == "messages_screen":
|
||||
context_dest = self.root.ids.messages_scrollview.active_conversation
|
||||
self.map_show_peer_location(context_dest)
|
||||
|
||||
def message_propagation_action(self, sender):
|
||||
if self.outbound_mode_paper:
|
||||
self.outbound_mode_paper = False
|
||||
|
@ -1289,6 +1295,10 @@ class SidebandApp(MDApp):
|
|||
self.sideband.save_configuration()
|
||||
self.update_ui_theme()
|
||||
|
||||
def save_advanced_stats(sender=None, event=None):
|
||||
self.sideband.config["advanced_stats"] = self.root.ids.settings_advanced_statistics.active
|
||||
self.sideband.save_configuration()
|
||||
|
||||
def save_notifications_on(sender=None, event=None):
|
||||
self.sideband.config["notifications_on"] = self.root.ids.settings_notifications_on.active
|
||||
self.sideband.save_configuration()
|
||||
|
@ -1377,6 +1387,9 @@ class SidebandApp(MDApp):
|
|||
self.root.ids.settings_eink_mode.active = self.sideband.config["eink_mode"]
|
||||
self.root.ids.settings_eink_mode.bind(active=save_eink_mode)
|
||||
|
||||
self.root.ids.settings_advanced_statistics.active = self.sideband.config["advanced_stats"]
|
||||
self.root.ids.settings_advanced_statistics.bind(active=save_advanced_stats)
|
||||
|
||||
self.root.ids.settings_start_announce.active = self.sideband.config["start_announce"]
|
||||
self.root.ids.settings_start_announce.bind(active=save_start_announce)
|
||||
|
||||
|
@ -2898,6 +2911,7 @@ class SidebandApp(MDApp):
|
|||
|
||||
self.sideband.config["telemetry_icon"] = self.root.ids.telemetry_icon_preview.icon
|
||||
self.sideband.save_configuration()
|
||||
self.own_appearance_changed = True
|
||||
|
||||
|
||||
def telemetry_enabled_toggle(self, sender=None, event=None):
|
||||
|
@ -2909,9 +2923,10 @@ class SidebandApp(MDApp):
|
|||
|
||||
def telemetry_location_toggle(self, sender=None, event=None):
|
||||
if self.root.ids.telemetry_s_location.active:
|
||||
if not check_permission("android.permission.ACCESS_COARSE_LOCATION") or not check_permission("android.permission.ACCESS_FINE_LOCATION"):
|
||||
RNS.log("Requesting location permission", RNS.LOG_DEBUG)
|
||||
request_permissions(["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])
|
||||
if RNS.vendor.platformutils.is_android():
|
||||
if not check_permission("android.permission.ACCESS_COARSE_LOCATION") or not check_permission("android.permission.ACCESS_FINE_LOCATION"):
|
||||
RNS.log("Requesting location permission", RNS.LOG_DEBUG)
|
||||
request_permissions(["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])
|
||||
|
||||
self.telemetry_save()
|
||||
|
||||
|
@ -2984,6 +2999,7 @@ class SidebandApp(MDApp):
|
|||
self.root.ids.telemetry_icon_preview.icon_color = color
|
||||
self.sideband.config["telemetry_fg"] = color
|
||||
self.sideband.save_configuration()
|
||||
self.own_appearance_changed = True
|
||||
if hasattr(self, "color_picker") and self.color_picker != None:
|
||||
self.color_picker.dismiss()
|
||||
self.color_picker = None
|
||||
|
@ -3000,6 +3016,8 @@ class SidebandApp(MDApp):
|
|||
color = selected_color[:-1] + [1]
|
||||
self.root.ids.telemetry_icon_preview.md_bg_color = color
|
||||
self.sideband.config["telemetry_bg"] = color
|
||||
self.sideband.save_configuration()
|
||||
self.own_appearance_changed = True
|
||||
if hasattr(self, "color_picker") and self.color_picker != None:
|
||||
self.color_picker.dismiss()
|
||||
self.color_picker = None
|
||||
|
@ -3057,7 +3075,7 @@ class SidebandApp(MDApp):
|
|||
from mapview import MapView
|
||||
mapview = MapView(zoom=self.sideband.config["map_zoom"], lat=self.sideband.config["map_lat"], lon=self.sideband.config["map_lon"])
|
||||
mapview.snap_to_zoom = False
|
||||
mapview.double_tap_zoom = False
|
||||
mapview.double_tap_zoom = True
|
||||
self.root.ids.map_layout.map = mapview
|
||||
self.root.ids.map_layout.add_widget(self.root.ids.map_layout.map)
|
||||
|
||||
|
@ -3073,11 +3091,71 @@ class SidebandApp(MDApp):
|
|||
self.map_update_markers()
|
||||
Clock.schedule_once(am_job, 0.6)
|
||||
|
||||
def close_location_error_dialog(self, sender=None):
|
||||
if hasattr(self, "location_error_dialog") and self.location_error_dialog != None:
|
||||
self.location_error_dialog.dismiss()
|
||||
|
||||
def map_show(self, location):
|
||||
RNS.log(str(location), RNS.LOG_WARNING)
|
||||
if hasattr(self.root.ids.map_layout, "map") and self.root.ids.map_layout.map:
|
||||
self.root.ids.map_layout.map.lat = location["latitude"]
|
||||
self.root.ids.map_layout.map.lon = location["longtitude"]
|
||||
self.root.ids.map_layout.map.zoom = 16
|
||||
|
||||
def map_show_peer_location(self, context_dest):
|
||||
location = self.sideband.peer_location(context_dest)
|
||||
if not location:
|
||||
self.location_error_dialog = MDDialog(
|
||||
title="No Location",
|
||||
text="During the last 24 hours, no location updates have been received from this peer. You can use the the [b]Situation Map[/b] to manually search for earlier telemetry.",
|
||||
buttons=[
|
||||
MDRectangleFlatButton(
|
||||
text="OK",
|
||||
font_size=dp(18),
|
||||
on_release=self.close_location_error_dialog
|
||||
)
|
||||
],
|
||||
)
|
||||
self.location_error_dialog.open()
|
||||
else:
|
||||
self.map_action()
|
||||
self.map_show(location)
|
||||
|
||||
def map_create_marker(self, source, telemetry, appearance):
|
||||
try:
|
||||
l = telemetry["location"]
|
||||
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.source_dest = source
|
||||
marker.location_time = l["last_update"]
|
||||
marker.icon = MDMapIconButton(
|
||||
icon=a_icon, icon_color=a_fg,
|
||||
md_bg_color=a_bg, theme_icon_color="Custom",
|
||||
icon_size=dp(32),
|
||||
)
|
||||
marker.icon._default_icon_pad = dp(16)
|
||||
marker.add_widget(marker.icon)
|
||||
|
||||
########
|
||||
# marker.badge = MDMapIconButton(
|
||||
# icon="network-strength-2", icon_color=[0,0,0,1],
|
||||
# md_bg_color=[1,1,1,1], theme_icon_color="Custom",
|
||||
# icon_size=dp(18),
|
||||
# )
|
||||
# marker.badge._default_icon_pad = dp(5)
|
||||
# marker.icon.add_widget(marker.badge)
|
||||
########
|
||||
|
||||
return marker
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Could not create map marker for "+RNS.prettyhexrep(source)+": "+str(e), RNS.LOG_ERROR)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
def map_update_markers(self, sender=None):
|
||||
# TODO: Remove
|
||||
# time_s = time.time()
|
||||
# RNS.log("Update map markers", RNS.LOG_WARNING)
|
||||
earliest = time.time() - self.sideband.config["map_history_limit"]
|
||||
telemetry_entries = self.sideband.list_telemetry(after=earliest)
|
||||
own_address = self.sideband.lxmf_destination.hash
|
||||
|
@ -3086,113 +3164,106 @@ class SidebandApp(MDApp):
|
|||
# Add own marker if available
|
||||
retain_own = False
|
||||
own_telemetry = self.sideband.get_telemetry()
|
||||
if own_telemetry != None and "location" in own_telemetry and own_telemetry["location"]["latitude"] != None and own_telemetry["location"]["longtitude"] != None:
|
||||
retain_own = True
|
||||
o = own_telemetry["location"]
|
||||
if not own_address in self.map_markers:
|
||||
# TODO: Remove
|
||||
RNS.log("Adding own marker", RNS.LOG_WARNING)
|
||||
marker = MapMarker(lat=o["latitude"], lon=o["longtitude"])
|
||||
marker.source_dest = own_address
|
||||
marker.latest_timestamp = o["last_update"]
|
||||
self.map_markers[own_address] = marker
|
||||
self.root.ids.map_layout.map.add_widget(marker)
|
||||
changes = True
|
||||
else:
|
||||
marker = self.map_markers[own_address]
|
||||
if o["last_update"] > marker.latest_timestamp:
|
||||
# TODO: Remove
|
||||
RNS.log("Updating own marker", RNS.LOG_WARNING)
|
||||
marker.latest_timestamp = o["last_update"]
|
||||
marker.lat = o["latitude"]
|
||||
marker.lon = o["longtitude"]
|
||||
changes = True
|
||||
else:
|
||||
# TODO: Remove
|
||||
RNS.log("Skipped updating own marker, no new location", RNS.LOG_WARNING)
|
||||
else:
|
||||
# TODO: Remove
|
||||
RNS.log("Not adding own marker, no data", RNS.LOG_WARNING)
|
||||
own_appearance = [
|
||||
self.sideband.config["telemetry_icon"],
|
||||
self.sideband.config["telemetry_fg"],
|
||||
self.sideband.config["telemetry_bg"]
|
||||
]
|
||||
|
||||
stale_markers = []
|
||||
for marker in self.map_markers:
|
||||
if not marker in telemetry_entries:
|
||||
if marker == own_address:
|
||||
if not retain_own:
|
||||
# TODO: Remove
|
||||
RNS.log("Setting own marker for removal: "+str(marker), RNS.LOG_WARNING)
|
||||
try:
|
||||
if own_telemetry != None and "location" in own_telemetry and own_telemetry["location"] != None and own_telemetry["location"]["latitude"] != None and own_telemetry["location"]["longtitude"] != None:
|
||||
retain_own = True
|
||||
|
||||
if not own_address in self.map_markers:
|
||||
RNS.log("Adding own marker", RNS.LOG_WARNING)
|
||||
marker = self.map_create_marker(own_address, own_telemetry, own_appearance)
|
||||
if marker != None:
|
||||
self.map_markers[own_address] = marker
|
||||
self.root.ids.map_layout.map.add_marker(marker)
|
||||
changes = True
|
||||
|
||||
else:
|
||||
marker = self.map_markers[own_address]
|
||||
o = own_telemetry["location"]
|
||||
if o["last_update"] > marker.location_time or (hasattr(self, "own_appearance_changed") and self.own_appearance_changed):
|
||||
marker.location_time = o["last_update"]
|
||||
marker.lat = o["latitude"]
|
||||
marker.lon = o["longtitude"]
|
||||
marker.icon.icon = own_appearance[0]
|
||||
marker.icon.icon_color = own_appearance[1]
|
||||
marker.icon.md_bg_color = own_appearance[2]
|
||||
self.own_appearance_changed = False
|
||||
changes = True
|
||||
|
||||
stale_markers = []
|
||||
for marker in self.map_markers:
|
||||
if not marker in telemetry_entries:
|
||||
if marker == own_address:
|
||||
if not retain_own:
|
||||
stale_markers.append(marker)
|
||||
else:
|
||||
stale_markers.append(marker)
|
||||
else:
|
||||
# TODO: Remove
|
||||
RNS.log("Setting marker for removal: "+str(marker), RNS.LOG_WARNING)
|
||||
stale_markers.append(marker)
|
||||
|
||||
for marker in stale_markers:
|
||||
try:
|
||||
self.root.ids.map_layout.map.remove_widget(self.map_markers[marker])
|
||||
self.map_markers.pop(marker)
|
||||
except Exception as e:
|
||||
RNS.log("Error while removing map marker: "+str(e), RNS.LOG_ERROR)
|
||||
for marker in stale_markers:
|
||||
try:
|
||||
self.root.ids.map_layout.map.remove_widget(self.map_markers[marker])
|
||||
self.map_markers.pop(marker)
|
||||
except Exception as e:
|
||||
RNS.log("Error while removing map marker: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Error while updating own map marker: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
for telemetry_source in telemetry_entries:
|
||||
skip = False
|
||||
|
||||
# TODO: Remove
|
||||
RNS.log("Processing telemetry for "+RNS.prettyhexrep(telemetry_source)+"/"+RNS.prettyhexrep(self.sideband.lxmf_destination.hash), RNS.LOG_WARNING)
|
||||
|
||||
if telemetry_source == own_address:
|
||||
# TODO: Remove
|
||||
RNS.log("Skipping own telemetry", RNS.LOG_WARNING)
|
||||
skip = True
|
||||
elif telemetry_source in self.map_markers:
|
||||
marker = self.map_markers[telemetry_source]
|
||||
newest_timestamp = telemetry_entries[telemetry_source][0][0]
|
||||
if newest_timestamp <= marker.latest_timestamp:
|
||||
try:
|
||||
skip = False
|
||||
if telemetry_source == own_address:
|
||||
skip = True
|
||||
elif telemetry_source in self.map_markers:
|
||||
marker = self.map_markers[telemetry_source]
|
||||
newest_timestamp = telemetry_entries[telemetry_source][0][0]
|
||||
if newest_timestamp <= marker.location_time:
|
||||
skip = True
|
||||
|
||||
latest_viewable = None
|
||||
if not skip:
|
||||
for telemetry_entry in telemetry_entries[telemetry_source]:
|
||||
telemetry_timestamp = telemetry_entry[0]
|
||||
telemetry_data = telemetry_entry[1]
|
||||
t = Telemeter.from_packed(telemetry_data)
|
||||
if t != None:
|
||||
telemetry = t.read_all()
|
||||
# TODO: Remove
|
||||
# RNS.log(str(telemetry)+" "+str(t), RNS.LOG_WARNING)
|
||||
if "location" in telemetry and telemetry["location"]["latitude"] != None and telemetry["location"]["longtitude"] != None:
|
||||
latest_viewable = telemetry
|
||||
break
|
||||
latest_viewable = None
|
||||
if not skip:
|
||||
for telemetry_entry in telemetry_entries[telemetry_source]:
|
||||
telemetry_timestamp = telemetry_entry[0]
|
||||
telemetry_data = telemetry_entry[1]
|
||||
t = Telemeter.from_packed(telemetry_data)
|
||||
if t != None:
|
||||
telemetry = t.read_all()
|
||||
if "location" in telemetry and telemetry["location"]["latitude"] != None and telemetry["location"]["longtitude"] != None:
|
||||
latest_viewable = telemetry
|
||||
break
|
||||
|
||||
if latest_viewable != None:
|
||||
l = latest_viewable["location"]
|
||||
if not telemetry_source in self.map_markers:
|
||||
marker = MapMarker(lat=l["latitude"], lon=l["longtitude"])
|
||||
marker.source_dest = telemetry_source
|
||||
marker.latest_timestamp = latest_viewable["time"]["utc"]
|
||||
self.map_markers[telemetry_source] = marker
|
||||
self.root.ids.map_layout.map.add_widget(marker)
|
||||
changes = True
|
||||
else:
|
||||
marker = self.map_markers[telemetry_source]
|
||||
marker.latest_timestamp = latest_viewable["time"]["utc"]
|
||||
marker.lat = l["latitude"]
|
||||
marker.lon = l["longtitude"]
|
||||
changes = True
|
||||
if latest_viewable != None:
|
||||
l = latest_viewable["location"]
|
||||
if not telemetry_source in self.map_markers:
|
||||
marker = self.map_create_marker(telemetry_source, latest_viewable, self.sideband.peer_appearance(telemetry_source))
|
||||
if marker != None:
|
||||
self.map_markers[telemetry_source] = marker
|
||||
self.root.ids.map_layout.map.add_marker(marker)
|
||||
changes = True
|
||||
else:
|
||||
marker = self.map_markers[telemetry_source]
|
||||
marker.location_time = latest_viewable["time"]["utc"]
|
||||
marker.lat = l["latitude"]
|
||||
marker.lon = l["longtitude"]
|
||||
appearance = self.sideband.peer_appearance(telemetry_source)
|
||||
marker.icon.icon = appearance[0]
|
||||
marker.icon.icon_color = appearance[1]
|
||||
marker.icon.md_bg_color = appearance[2]
|
||||
changes = True
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Error while updating map entry for "+RNS.prettyhexrep(telemetry_source)+": "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
self.last_map_update = time.time()
|
||||
if changes:
|
||||
mv = self.root.ids.map_layout.map
|
||||
mv.trigger_update(True)
|
||||
|
||||
# TODO: Remove
|
||||
# RNS.log("Updated map markers in "+RNS.prettytime(time.time()-time_s), RNS.LOG_WARNING)
|
||||
|
||||
|
||||
def map_add_marker(self, marker):
|
||||
marker = MapMarker(lat=0.0, lon=0.0)
|
||||
self.root.ids.map_layout.map.add_widget(marker)
|
||||
|
||||
### Guide screen
|
||||
######################################
|
||||
def close_guide_action(self, sender=None):
|
||||
|
@ -3307,6 +3378,9 @@ Thank you very much for using Free Communications Systems.
|
|||
class CustomOneLineIconListItem(OneLineIconListItem):
|
||||
icon = StringProperty()
|
||||
|
||||
class MDMapIconButton(MDIconButton):
|
||||
pass
|
||||
|
||||
def run():
|
||||
SidebandApp().run()
|
||||
|
||||
|
|
|
@ -327,9 +327,9 @@ class MarkerMapLayer(MapLayer):
|
|||
marker.y = int(y - marker.height * marker.anchor_y)
|
||||
if hasattr(marker, "children"):
|
||||
if marker.children != None and len(marker.children) > 0:
|
||||
c = marker.children[0]
|
||||
c.x = marker.x
|
||||
c.y = marker.y+dp(16)
|
||||
for c in marker.children:
|
||||
c.x = marker.x
|
||||
c.y = marker.y+dp(16)
|
||||
|
||||
def unload(self):
|
||||
self.clear_widgets()
|
||||
|
|
|
@ -73,14 +73,14 @@ class SidebandCore():
|
|||
SERVICE_JOB_INTERVAL = 1
|
||||
PERIODIC_JOBS_INTERVAL = 60
|
||||
PERIODIC_SYNC_RETRY = 360
|
||||
# TODO: Reset
|
||||
# TELEMETRY_INTERVAL = 60
|
||||
TELEMETRY_INTERVAL = 10
|
||||
TELEMETRY_INTERVAL = 60
|
||||
|
||||
IF_CHANGE_ANNOUNCE_MIN_INTERVAL = 6 # In seconds
|
||||
AUTO_ANNOUNCE_RANDOM_MIN = 90 # In minutes
|
||||
AUTO_ANNOUNCE_RANDOM_MAX = 480 # In minutes
|
||||
|
||||
DEFAULT_APPEARANCE = ["alpha-p-circle-outline", [0,0,0,1], [1,1,1,1]]
|
||||
|
||||
aspect_filter = "lxmf.delivery"
|
||||
def received_announce(self, destination_hash, announced_identity, app_data):
|
||||
# Add the announce to the directory announce
|
||||
|
@ -305,7 +305,7 @@ class SidebandCore():
|
|||
|
||||
# Telemetry
|
||||
self.config["telemetry_enabled"] = False
|
||||
self.config["telemetry_icon"] = "alpha-p-circle-outline"
|
||||
self.config["telemetry_icon"] = SidebandCore.DEFAULT_APPEARANCE[0]
|
||||
self.config["telemetry_send_to_trusted"] = False
|
||||
self.config["telemetry_send_to_collector"] = False
|
||||
|
||||
|
@ -315,6 +315,7 @@ class SidebandCore():
|
|||
self._db_initstate()
|
||||
self._db_initpersistent()
|
||||
self._db_inittelemetry()
|
||||
self._db_upgradetables()
|
||||
|
||||
self.__save_config()
|
||||
|
||||
|
@ -338,6 +339,8 @@ class SidebandCore():
|
|||
self.config["debug"] = False
|
||||
if not "dark_ui" in self.config:
|
||||
self.config["dark_ui"] = True
|
||||
if not "advanced_stats" in self.config:
|
||||
self.config["advanced_stats"] = False
|
||||
if not "lxmf_periodic_sync" in self.config:
|
||||
self.config["lxmf_periodic_sync"] = False
|
||||
if not "lxmf_ignore_unknown" in self.config:
|
||||
|
@ -454,11 +457,11 @@ class SidebandCore():
|
|||
self.config["telemetry_send_to_collector"] = False
|
||||
|
||||
if not "telemetry_icon" in self.config:
|
||||
self.config["telemetry_icon"] = "alpha-p-circle-outline"
|
||||
self.config["telemetry_icon"] = SidebandCore.DEFAULT_APPEARANCE[0]
|
||||
if not "telemetry_fg" in self.config:
|
||||
self.config["telemetry_fg"] = [0,0,0,1]
|
||||
self.config["telemetry_fg"] = SidebandCore.DEFAULT_APPEARANCE[1]
|
||||
if not "telemetry_bg" in self.config:
|
||||
self.config["telemetry_bg"] = [1,1,1,1]
|
||||
self.config["telemetry_bg"] = SidebandCore.DEFAULT_APPEARANCE[2]
|
||||
if not "telemetry_send_appearance" in self.config:
|
||||
self.config["telemetry_send_appearance"] = False
|
||||
|
||||
|
@ -503,6 +506,7 @@ class SidebandCore():
|
|||
self._db_initstate()
|
||||
self._db_initpersistent()
|
||||
self._db_inittelemetry()
|
||||
self._db_upgradetables()
|
||||
self.__db_indices()
|
||||
|
||||
def __reload_config(self):
|
||||
|
@ -648,6 +652,9 @@ class SidebandCore():
|
|||
RNS.log("Error while getting peer name: "+str(e), RNS.LOG_ERROR)
|
||||
return ""
|
||||
|
||||
def peer_appearance(self, context_dest):
|
||||
return self._db_get_appearance(context_dest) or SidebandCore.DEFAULT_APPEARANCE
|
||||
|
||||
def peer_display_name(self, context_dest):
|
||||
try:
|
||||
existing_conv = self._db_conversation(context_dest)
|
||||
|
@ -730,6 +737,31 @@ class SidebandCore():
|
|||
def list_telemetry(self, context_dest = None, after = None, before = None, limit = None):
|
||||
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]
|
||||
|
||||
return []
|
||||
|
||||
def peer_location(self, context_dest):
|
||||
after_time = time.time()-24*60*60
|
||||
pts = self.peer_telemetry(context_dest, after=after_time)
|
||||
for pt in pts:
|
||||
try:
|
||||
t = Telemeter.from_packed(pt[1]).read_all()
|
||||
RNS.log(str(t), RNS.LOG_WARNING)
|
||||
if "location" in t:
|
||||
l = t["location"]
|
||||
if "latitude" in l and "longtitude" in l:
|
||||
if l["latitude"] != None and l["longtitude"] != None:
|
||||
return l
|
||||
except:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
def list_messages(self, context_dest, after = None, before = None, limit = None):
|
||||
result = self._db_messages(context_dest, after, before, limit)
|
||||
if result != None:
|
||||
|
@ -829,7 +861,7 @@ class SidebandCore():
|
|||
dbc = db.cursor()
|
||||
|
||||
dbc.execute("DROP TABLE IF EXISTS lxm")
|
||||
dbc.execute("CREATE TABLE lxm (lxm_hash BLOB PRIMARY KEY, dest BLOB, source BLOB, title BLOB, tx_ts INTEGER, rx_ts INTEGER, state INTEGER, method INTEGER, t_encrypted INTEGER, t_encryption INTEGER, data BLOB)")
|
||||
dbc.execute("CREATE TABLE lxm (lxm_hash BLOB PRIMARY KEY, dest BLOB, source BLOB, title BLOB, tx_ts INTEGER, rx_ts INTEGER, state INTEGER, method INTEGER, t_encrypted INTEGER, t_encryption INTEGER, data BLOB, extra BLOB)")
|
||||
|
||||
dbc.execute("DROP TABLE IF EXISTS conv")
|
||||
dbc.execute("CREATE TABLE conv (dest_context BLOB PRIMARY KEY, last_tx INTEGER, last_rx INTEGER, unread INTEGER, type INTEGER, trust INTEGER, name BLOB, data BLOB)")
|
||||
|
@ -837,6 +869,9 @@ class SidebandCore():
|
|||
dbc.execute("DROP TABLE IF EXISTS announce")
|
||||
dbc.execute("CREATE TABLE announce (id PRIMARY KEY, received INTEGER, source BLOB, data BLOB, dest_type BLOB)")
|
||||
|
||||
dbc.execute("DROP TABLE IF EXISTS telemetry")
|
||||
dbc.execute("CREATE TABLE IF NOT EXISTS telemetry (id INTEGER PRIMARY KEY, dest_context BLOB, ts INTEGER, data BLOB)")
|
||||
|
||||
dbc.execute("DROP TABLE IF EXISTS state")
|
||||
dbc.execute("CREATE TABLE state (property BLOB PRIMARY KEY, value BLOB)")
|
||||
|
||||
|
@ -853,6 +888,23 @@ class SidebandCore():
|
|||
dbc.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_conv_dest_context ON conv(dest_context)")
|
||||
db.commit()
|
||||
|
||||
def _db_inittelemetry(self):
|
||||
db = self.__db_connect()
|
||||
dbc = db.cursor()
|
||||
|
||||
dbc.execute("CREATE TABLE IF NOT EXISTS telemetry (id INTEGER PRIMARY KEY, dest_context BLOB, ts INTEGER, data BLOB)")
|
||||
db.commit()
|
||||
|
||||
def _db_upgradetables(self):
|
||||
# TODO: Remove this again at some point in the future
|
||||
db = self.__db_connect()
|
||||
dbc = db.cursor()
|
||||
dbc.execute("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'lxm' AND sql LIKE '%extra%'")
|
||||
result = dbc.fetchall()
|
||||
if len(result) == 0:
|
||||
dbc.execute("ALTER TABLE lxm ADD COLUMN extra BLOB")
|
||||
db.commit()
|
||||
|
||||
def _db_initstate(self):
|
||||
db = self.__db_connect()
|
||||
dbc = db.cursor()
|
||||
|
@ -930,13 +982,6 @@ class SidebandCore():
|
|||
dbc.execute("CREATE TABLE IF NOT EXISTS persistent (property BLOB PRIMARY KEY, value BLOB)")
|
||||
db.commit()
|
||||
|
||||
def _db_inittelemetry(self):
|
||||
db = self.__db_connect()
|
||||
dbc = db.cursor()
|
||||
|
||||
dbc.execute("CREATE TABLE IF NOT EXISTS telemetry (id INTEGER PRIMARY KEY, dest_context BLOB, ts INTEGER, data BLOB)")
|
||||
db.commit()
|
||||
|
||||
def _db_getpersistent(self, prop):
|
||||
try:
|
||||
db = self.__db_connect()
|
||||
|
@ -1079,10 +1124,7 @@ class SidebandCore():
|
|||
|
||||
return results
|
||||
|
||||
def _db_save_telemetry(self, context_dest, telemetry):
|
||||
# TODO: Remove
|
||||
# RNS.log("Saving telemetry for "+RNS.prettyhexrep(context_dest), RNS.LOG_WARNING)
|
||||
|
||||
def _db_save_telemetry(self, context_dest, telemetry, physical_link = None):
|
||||
try:
|
||||
remote_telemeter = Telemeter.from_packed(telemetry)
|
||||
telemetry_timestamp = remote_telemeter.read_all()["time"]["utc"]
|
||||
|
@ -1095,9 +1137,15 @@ class SidebandCore():
|
|||
result = dbc.fetchall()
|
||||
|
||||
if len(result) != 0:
|
||||
# TODO: Remove
|
||||
# RNS.log("Telemetry entry already exists, ignoring", RNS.LOG_WARNING)
|
||||
return
|
||||
|
||||
if physical_link != None and len(physical_link) != 0:
|
||||
remote_telemeter.synthesize("physical_link")
|
||||
if "rssi" in physical_link: remote_telemeter.sensors["physical_link"].rssi = physical_link["rssi"]
|
||||
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()
|
||||
RNS.log("PACKED: "+str(remote_telemeter.read_all()), RNS.LOG_WARNING)
|
||||
|
||||
query = "INSERT INTO telemetry (dest_context, ts, data) values (?, ?, ?)"
|
||||
data = (context_dest, telemetry_timestamp, telemetry)
|
||||
|
@ -1110,25 +1158,44 @@ class SidebandCore():
|
|||
self.db = None
|
||||
|
||||
def _db_update_appearance(self, context_dest, timestamp, appearance):
|
||||
# TODO: Remove
|
||||
# RNS.log("Updating appearance for "+RNS.prettyhexrep(context_dest), RNS.LOG_WARNING)
|
||||
|
||||
conv = self._db_conversation(context_dest)
|
||||
data_dict = conv["data"]
|
||||
if data_dict == None:
|
||||
data_dict = {}
|
||||
|
||||
data_dict["appearance"] = appearance
|
||||
packed_dict = msgpack.packb(data_dict)
|
||||
if data_dict["appearance"] != appearance:
|
||||
data_dict["appearance"] = appearance
|
||||
packed_dict = msgpack.packb(data_dict)
|
||||
|
||||
db = self.__db_connect()
|
||||
dbc = db.cursor()
|
||||
db = self.__db_connect()
|
||||
dbc = db.cursor()
|
||||
|
||||
query = "UPDATE conv set data = ? where dest_context = ?"
|
||||
data = (packed_dict, context_dest)
|
||||
dbc.execute(query, data)
|
||||
result = dbc.fetchall()
|
||||
db.commit()
|
||||
query = "UPDATE conv set data = ? where dest_context = ?"
|
||||
data = (packed_dict, context_dest)
|
||||
dbc.execute(query, data)
|
||||
result = dbc.fetchall()
|
||||
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]
|
||||
|
||||
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
|
||||
|
||||
|
||||
def _db_conversation_set_telemetry(self, context_dest, send_telemetry=False):
|
||||
conv = self._db_conversation(context_dest)
|
||||
|
@ -1437,6 +1504,12 @@ class SidebandCore():
|
|||
|
||||
if lxm.desired_method == LXMF.LXMessage.PAPER:
|
||||
lxm.paper_packed = paper_packed_lxm
|
||||
|
||||
extras = None
|
||||
try:
|
||||
extras = msgpack.unpackb(entry[11])
|
||||
except:
|
||||
pass
|
||||
|
||||
message = {
|
||||
"hash": lxm.hash,
|
||||
|
@ -1448,7 +1521,8 @@ class SidebandCore():
|
|||
"sent": lxm.timestamp,
|
||||
"state": entry[6],
|
||||
"method": entry[7],
|
||||
"lxm": lxm
|
||||
"lxm": lxm,
|
||||
"extras": extras,
|
||||
}
|
||||
|
||||
messages.append(message)
|
||||
|
@ -1470,7 +1544,14 @@ class SidebandCore():
|
|||
else:
|
||||
packed_lxm = lxm.packed
|
||||
|
||||
query = "INSERT INTO lxm (lxm_hash, dest, source, title, tx_ts, rx_ts, state, method, t_encrypted, t_encryption, data) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
extras = {}
|
||||
if lxm.rssi or lxm.snr or lxm.q:
|
||||
extras["rssi"] = lxm.rssi
|
||||
extras["snr"] = lxm.snr
|
||||
extras["q"] = lxm.q
|
||||
extras = msgpack.packb(extras)
|
||||
|
||||
query = "INSERT INTO lxm (lxm_hash, dest, source, title, tx_ts, rx_ts, state, method, t_encrypted, t_encryption, data, extra) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
data = (
|
||||
lxm.hash,
|
||||
lxm.destination_hash,
|
||||
|
@ -1483,10 +1564,10 @@ class SidebandCore():
|
|||
lxm.transport_encrypted,
|
||||
lxm.transport_encryption,
|
||||
packed_lxm,
|
||||
extras
|
||||
)
|
||||
|
||||
dbc.execute(query, data)
|
||||
|
||||
db.commit()
|
||||
|
||||
if not originator and lxm.fields != None:
|
||||
|
@ -1494,7 +1575,12 @@ class SidebandCore():
|
|||
self._db_update_appearance(context_dest, lxm.timestamp, lxm.fields[LXMF.FIELD_ICON_APPEARANCE])
|
||||
|
||||
if LXMF.FIELD_TELEMETRY in lxm.fields:
|
||||
self._db_save_telemetry(context_dest, lxm.fields[LXMF.FIELD_TELEMETRY])
|
||||
physical_link = {}
|
||||
if lxm.rssi or lxm.snr or lxm.q:
|
||||
physical_link["rssi"] = lxm.rssi
|
||||
physical_link["snr"] = lxm.snr
|
||||
physical_link["q"] = lxm.q
|
||||
self._db_save_telemetry(context_dest, lxm.fields[LXMF.FIELD_TELEMETRY], physical_link=physical_link)
|
||||
|
||||
self.__event_conversation_changed(context_dest)
|
||||
|
||||
|
@ -2258,7 +2344,7 @@ class SidebandCore():
|
|||
fields = {}
|
||||
if send_appearance:
|
||||
# TODO: REMOVE
|
||||
# RNS.log("Sending appearance", RNS.LOG_WARNING)
|
||||
RNS.log("Sending appearance", RNS.LOG_WARNING)
|
||||
def fth(c):
|
||||
r = c[0]; g = c[1]; b = c[2]
|
||||
r = min(max(0, r), 1); g = min(max(0, g), 1); b = min(max(0, b), 1)
|
||||
|
@ -2273,7 +2359,7 @@ class SidebandCore():
|
|||
|
||||
if send_telemetry:
|
||||
# TODO: REMOVE
|
||||
# RNS.log("Sending telemetry", RNS.LOG_WARNING)
|
||||
RNS.log("Sending telemetry", RNS.LOG_WARNING)
|
||||
fields[LXMF.FIELD_TELEMETRY] = self.latest_packed_telemetry
|
||||
|
||||
return fields
|
||||
|
@ -2377,9 +2463,6 @@ class SidebandCore():
|
|||
self.setstate("lxm_uri_ingest.result", response)
|
||||
|
||||
def lxm_ingest(self, message, originator = False):
|
||||
# TODO: Remove
|
||||
RNS.log("MESSAGE FIELDS: "+str(message.fields), RNS.LOG_WARNING)
|
||||
|
||||
should_notify = False
|
||||
is_trusted = False
|
||||
unread_reason_tx = False
|
||||
|
@ -2535,7 +2618,7 @@ class SidebandCore():
|
|||
if message.unverified_reason == LXMF.LXMessage.SOURCE_UNKNOWN:
|
||||
signature_string = "Cannot verify, source is unknown"
|
||||
|
||||
RNS.log("LXMF delivery "+str(time_string)+". "+str(signature_string)+".")
|
||||
RNS.log("LXMF delivery "+str(time_string)+". "+str(signature_string)+".", RNS.LOG_DEBUG)
|
||||
|
||||
try:
|
||||
if self.config["lxmf_ignore_unknown"] == True:
|
||||
|
|
|
@ -115,6 +115,7 @@ MDNavigationLayout:
|
|||
[['menu', lambda x: nav_drawer.set_state("open")]]
|
||||
right_action_items:
|
||||
[
|
||||
['map-search', lambda x: root.ids.screen_manager.app.peer_show_location_action(self)],
|
||||
['lan-connect', lambda x: root.ids.screen_manager.app.message_propagation_action(self)],
|
||||
['close', lambda x: root.ids.screen_manager.app.close_messages_action(self)],
|
||||
]
|
||||
|
@ -1009,7 +1010,7 @@ MDNavigationLayout:
|
|||
MDIconButton:
|
||||
pos_hint: {"center_x": .5}
|
||||
id: telemetry_icon_preview
|
||||
icon: "alpha-p-circle-outline"
|
||||
icon: "account"
|
||||
type: "large"
|
||||
theme_icon_color: "Custom"
|
||||
icon_color: [0, 0, 0, 1]
|
||||
|
@ -1018,6 +1019,7 @@ MDNavigationLayout:
|
|||
size_hint_y: None
|
||||
# width: dp(64)
|
||||
height: dp(80)
|
||||
on_release: root.ids.screen_manager.app.icons_action(self)
|
||||
|
||||
|
||||
MDRectangleFlatIconButton:
|
||||
|
@ -1589,6 +1591,21 @@ MDNavigationLayout:
|
|||
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: "Advanced Statistics"
|
||||
font_style: "H6"
|
||||
|
||||
MDSwitch:
|
||||
id: settings_advanced_statistics
|
||||
pos_hint: {"center_y": 0.3}
|
||||
active: False
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "horizontal"
|
||||
size_hint_y: None
|
||||
|
|
Loading…
Reference in New Issue