Added telemetry system, location sharing and map view for shared locations

This commit is contained in:
Mark Qvist 2023-10-22 01:12:55 +02:00
parent a9160b558b
commit 314499109c
4 changed files with 322 additions and 148 deletions

View File

@ -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()

View File

@ -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()

View File

@ -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,10 +1137,16 @@ 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)
dbc.execute(query, data)
@ -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()
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
query = "UPDATE conv set data = ? where dest_context = ?"
data = (packed_dict, context_dest)
dbc.execute(query, data)
result = dbc.fetchall()
db.commit()
def _db_conversation_set_telemetry(self, context_dest, send_telemetry=False):
conv = self._db_conversation(context_dest)
@ -1438,6 +1505,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,
"dest": lxm.destination_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:

View File

@ -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