Refactored telemetry screen

This commit is contained in:
Mark Qvist 2023-10-29 10:43:34 +01:00
parent 93a0b5fb55
commit c39a87a5f3
4 changed files with 970 additions and 888 deletions

View File

@ -52,9 +52,7 @@ if RNS.vendor.platformutils.get_platform() != "android":
local = os.path.dirname(__file__) local = os.path.dirname(__file__)
sys.path.append(local) sys.path.append(local)
from typing import Union
from kivymd.app import MDApp from kivymd.app import MDApp
from kivymd.icon_definitions import md_icons
from kivy.core.window import Window from kivy.core.window import Window
from kivy.core.clipboard import Clipboard from kivy.core.clipboard import Clipboard
from kivy.base import EventLoop from kivy.base import EventLoop
@ -65,7 +63,6 @@ from kivy.uix.screenmanager import ScreenManager
from kivy.uix.screenmanager import FadeTransition, NoTransition from kivy.uix.screenmanager import FadeTransition, NoTransition
from kivymd.uix.list import OneLineIconListItem from kivymd.uix.list import OneLineIconListItem
from kivy.properties import StringProperty from kivy.properties import StringProperty
from kivymd.uix.pickers import MDColorPicker
from kivymd.uix.button import BaseButton, MDIconButton from kivymd.uix.button import BaseButton, MDIconButton
from kivymd.uix.filemanager import MDFileManager from kivymd.uix.filemanager import MDFileManager
from kivymd.toast import toast from kivymd.toast import toast
@ -82,6 +79,7 @@ if RNS.vendor.platformutils.get_platform() == "android":
from ui.layouts import * from ui.layouts import *
from ui.conversations import Conversations, MsgSync, NewConv from ui.conversations import Conversations, MsgSync, NewConv
from ui.telemetry import Telemetry
from ui.objectdetails import ObjectDetails from ui.objectdetails import ObjectDetails
from ui.announces import Announces from ui.announces import Announces
from ui.messages import Messages, ts_format, messages_screen_kv from ui.messages import Messages, ts_format, messages_screen_kv
@ -102,6 +100,7 @@ else:
from .ui.layouts import * from .ui.layouts import *
from .ui.conversations import Conversations, MsgSync, NewConv from .ui.conversations import Conversations, MsgSync, NewConv
from .ui.announces import Announces from .ui.announces import Announces
from .ui.telemetry import Telemetry
from .ui.objectdetails import ObjectDetails from .ui.objectdetails import ObjectDetails
from .ui.messages import Messages, ts_format, messages_screen_kv from .ui.messages import Messages, ts_format, messages_screen_kv
from .ui.helpers import ContentNavigationDrawer, DrawerList, IconListItem from .ui.helpers import ContentNavigationDrawer, DrawerList, IconListItem
@ -147,12 +146,14 @@ class SidebandApp(MDApp):
self.sideband = SidebandCore(self, is_client=False, verbose=(args.verbose or __debug_build__)) self.sideband = SidebandCore(self, is_client=False, verbose=(args.verbose or __debug_build__))
self.set_ui_theme() self.set_ui_theme()
self.dark_theme_text_color = dark_theme_text_color
self.conversations_view = None self.conversations_view = None
self.messages_view = None self.messages_view = None
self.map = None self.map = None
self.map_layer = None self.map_layer = None
self.map_screen = None self.map_screen = None
self.telemetry_screen = None
self.map_cache = self.sideband.map_cache self.map_cache = self.sideband.map_cache
self.offline_source = None self.offline_source = None
self.map_settings_screen = None self.map_settings_screen = None
@ -794,6 +795,10 @@ class SidebandApp(MDApp):
self.close_sub_map_action() self.close_sub_map_action()
elif self.root.ids.screen_manager.current == "object_details_screen": elif self.root.ids.screen_manager.current == "object_details_screen":
self.object_details_screen.close_action() self.object_details_screen.close_action()
elif self.root.ids.screen_manager.current == "sensors_screen":
self.close_sub_telemetry_action()
elif self.root.ids.screen_manager.current == "icons_screen":
self.close_sub_telemetry_action()
else: else:
self.open_conversations(direction="right") self.open_conversations(direction="right")
@ -876,6 +881,10 @@ class SidebandApp(MDApp):
self.object_details_screen.close_action() self.object_details_screen.close_action()
elif self.root.ids.screen_manager.current == "map_settings_screen": elif self.root.ids.screen_manager.current == "map_settings_screen":
self.close_sub_map_action() self.close_sub_map_action()
elif self.root.ids.screen_manager.current == "sensors_screen":
self.close_sub_telemetry_action()
elif self.root.ids.screen_manager.current == "icons_screen":
self.close_sub_telemetry_action()
else: else:
self.open_conversations(direction="right") self.open_conversations(direction="right")
@ -3063,221 +3072,18 @@ class SidebandApp(MDApp):
def telemetry_init(self): def telemetry_init(self):
if not self.telemetry_ready: if not self.telemetry_ready:
if not self.root.ids.screen_manager.has_screen("telemetry_screen"): self.telemetry_screen = Telemetry(self)
self.telemetry_screen = Builder.load_string(layout_telemetry_screen)
self.telemetry_screen.app = self
self.root.ids.screen_manager.add_widget(self.telemetry_screen)
self.telemetry_screen.ids.telemetry_collector.bind(focus=self.telemetry_save)
if self.sideband.config["telemetry_collector"] == None:
self.telemetry_screen.ids.telemetry_collector.text = ""
else:
self.telemetry_screen.ids.telemetry_collector.text = RNS.hexrep(self.sideband.config["telemetry_collector"], delimit=False)
self.telemetry_screen.ids.telemetry_icon_preview.icon_color = self.sideband.config["telemetry_fg"]
self.telemetry_screen.ids.telemetry_icon_preview.md_bg_color = self.sideband.config["telemetry_bg"]
self.telemetry_screen.ids.telemetry_icon_preview.icon = self.sideband.config["telemetry_icon"]
self.telemetry_screen.ids.telemetry_enabled.active = self.sideband.config["telemetry_enabled"]
self.telemetry_screen.ids.telemetry_enabled.bind(active=self.telemetry_enabled_toggle)
self.telemetry_screen.ids.telemetry_send_to_collector.active = self.sideband.config["telemetry_send_to_collector"]
self.telemetry_screen.ids.telemetry_send_to_collector.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_send_to_trusted.active = self.sideband.config["telemetry_send_to_trusted"]
self.telemetry_screen.ids.telemetry_send_to_trusted.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_display_trusted_only.active = self.sideband.config["telemetry_display_trusted_only"]
self.telemetry_screen.ids.telemetry_display_trusted_only.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_send_appearance.active = self.sideband.config["telemetry_send_appearance"]
self.telemetry_screen.ids.telemetry_send_appearance.bind(active=self.telemetry_save)
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)
self.telemetry_screen.ids.telemetry_s_barometer.active = self.sideband.config["telemetry_s_pressure"]
self.telemetry_screen.ids.telemetry_s_barometer.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_temperature.active = self.sideband.config["telemetry_s_temperature"]
self.telemetry_screen.ids.telemetry_s_temperature.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_humidity.active = self.sideband.config["telemetry_s_humidity"]
self.telemetry_screen.ids.telemetry_s_humidity.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_compass.active = self.sideband.config["telemetry_s_magnetic_field"]
self.telemetry_screen.ids.telemetry_s_compass.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_light.active = self.sideband.config["telemetry_s_ambient_light"]
self.telemetry_screen.ids.telemetry_s_light.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_gravity.active = self.sideband.config["telemetry_s_gravity"]
self.telemetry_screen.ids.telemetry_s_gravity.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_gyroscope.active = self.sideband.config["telemetry_s_angular_velocity"]
self.telemetry_screen.ids.telemetry_s_gyroscope.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_accelerometer.active = self.sideband.config["telemetry_s_acceleration"]
self.telemetry_screen.ids.telemetry_s_accelerometer.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_proximity.active = self.sideband.config["telemetry_s_proximity"]
self.telemetry_screen.ids.telemetry_s_proximity.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_information.active = self.sideband.config["telemetry_s_information"]
self.telemetry_screen.ids.telemetry_s_information.bind(active=self.telemetry_save)
self.telemetry_screen.ids.telemetry_s_information_text.text = str(self.sideband.config["telemetry_s_information_text"])
self.telemetry_screen.ids.telemetry_s_information_text.bind(focus=self.telemetry_save)
self.telemetry_ready = True self.telemetry_ready = True
def telemetry_set_icon(self, text="", search=False):
if text in md_icons.keys():
self.telemetry_screen.ids.telemetry_icon_preview.icon = text
else:
self.telemetry_screen.ids.telemetry_icon_preview.icon = "alpha-p-circle-outline"
self.sideband.config["telemetry_icon"] = self.telemetry_screen.ids.telemetry_icon_preview.icon
self.sideband.save_configuration()
self.own_appearance_changed = True
def telemetry_enabled_toggle(self, sender=None, event=None):
self.telemetry_save()
if self.telemetry_screen.ids.telemetry_enabled.active:
self.sideband.run_telemetry()
else:
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"):
RNS.log("Requesting location permission", RNS.LOG_DEBUG)
request_permissions(["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])
self.telemetry_save()
def telemetry_save(self, sender=None, event=None):
if len(self.telemetry_screen.ids.telemetry_collector.text) != 32:
self.telemetry_screen.ids.telemetry_collector.text = ""
self.sideband.config["telemetry_collector"] = None
else:
try:
self.sideband.config["telemetry_collector"] = bytes.fromhex(self.telemetry_screen.ids.telemetry_collector.text)
except:
self.telemetry_screen.ids.telemetry_collector.text = ""
self.sideband.config["telemetry_collector"] = None
self.sideband.config["telemetry_enabled"] = self.telemetry_screen.ids.telemetry_enabled.active
self.sideband.config["telemetry_send_to_collector"] = self.telemetry_screen.ids.telemetry_send_to_collector.active
self.sideband.config["telemetry_send_to_trusted"] = self.telemetry_screen.ids.telemetry_send_to_trusted.active
self.sideband.config["telemetry_display_trusted_only"] = self.telemetry_screen.ids.telemetry_display_trusted_only.active
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
self.sideband.config["telemetry_s_humidity"] = self.telemetry_screen.ids.telemetry_s_humidity.active
self.sideband.config["telemetry_s_magnetic_field"] = self.telemetry_screen.ids.telemetry_s_compass.active
self.sideband.config["telemetry_s_ambient_light"] = self.telemetry_screen.ids.telemetry_s_light.active
self.sideband.config["telemetry_s_gravity"] = self.telemetry_screen.ids.telemetry_s_gravity.active
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
run_telemetry_update = False
if self.sideband.config["telemetry_s_information"] != self.telemetry_screen.ids.telemetry_s_information.active:
self.sideband.config["telemetry_s_information"] = self.telemetry_screen.ids.telemetry_s_information.active
run_telemetry_update = True
if self.sideband.config["telemetry_s_information_text"] != self.telemetry_screen.ids.telemetry_s_information_text.text:
self.sideband.config["telemetry_s_information_text"] = self.telemetry_screen.ids.telemetry_s_information_text.text
run_telemetry_update = True
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)
if self.sideband.config["telemetry_s_fixed_altitude"] != alt:
self.sideband.config["telemetry_s_fixed_altitude"] = alt
run_telemetry_update = True
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])
if self.sideband.config["telemetry_s_fixed_latlon"] != [lat, lon]:
run_telemetry_update = True
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()
if run_telemetry_update:
self.sideband.update_telemetry()
else:
self.sideband.setstate("app.flags.last_telemetry", time.time())
def telemetry_action(self, sender=None, direction="left"): def telemetry_action(self, sender=None, direction="left"):
self.telemetry_init() self.telemetry_init()
self.telemetry_screen.ids.telemetry_scrollview.effect_cls = ScrollEffect
info = "\nSideband allows you to securely share telemetry, such as location and sensor data, with people, custom programs, machines or other system over LXMF. You have complete control over what kind of telemetry to send, and who you share it with.\n\nTelemetry data is never sent to, via or processed by any external services or servers, but is carried exclusively within encrypted LXMF messages over Reticulum.\n\nWhen telemetry is enabled, it is possible to embed telemetry data in normal messages on a per-peer basis. You can control this from the [b]Conversations[/b] list, by selecting the [b]Edit[/b] option for the relevant peer.\n\nYou can also define a [b]Telemetry Collector[/b], that Sideband will automatically send telemetry to on a periodic basis - for example your Nomad Network home node.\n"
info3 = "\nTo include a specific type of telemetry data while sending, it must be enabled below. Please note that some sensor types are not supported on all devices. Sideband will only be able to read a specific type of sensor if your device actually includes hardware for it.\n"
if self.theme_cls.theme_style == "Dark":
info = "[color=#"+dark_theme_text_color+"]"+info+"[/color]"
# info2 = "[color=#"+dark_theme_text_color+"]"+info2+"[/color]"
info3 = "[color=#"+dark_theme_text_color+"]"+info3+"[/color]"
self.telemetry_screen.ids.telemetry_info.text = info
# self.root.ids.telemetry_info2.text = info2
self.telemetry_screen.ids.telemetry_info3.text = info3
self.root.ids.screen_manager.transition.direction = direction self.root.ids.screen_manager.transition.direction = direction
self.root.ids.screen_manager.current = "telemetry_screen" self.root.ids.screen_manager.current = "telemetry_screen"
self.root.ids.nav_drawer.set_state("closed") self.root.ids.nav_drawer.set_state("closed")
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current) self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
def converse_from_telemetry(self, sender=None): def close_sub_telemetry_action(self, sender=None):
if self.object_details_screen != None: self.telemetry_action(direction="right")
context_dest = self.object_details_screen.object_hash
if not self.object_details_screen.object_hash == self.sideband.lxmf_destination.hash:
self.open_conversation(context_dest)
def telemetry_copy(self, sender=None):
Clipboard.copy(str(self.sideband.get_telemetry()))
self.sideband.update_telemetry()
def telemetry_send_update(self, sender=None): def telemetry_send_update(self, sender=None):
# TODO: Implement # TODO: Implement
@ -3287,98 +3093,6 @@ class SidebandApp(MDApp):
# TODO: Implement # TODO: Implement
pass pass
def telemetry_fg_color(self, sender=None):
color_picker = MDColorPicker(size_hint=(0.85, 0.85))
self.color_picker = color_picker
color_picker.open()
color_picker.bind(on_release=self.telemetry_fg_select)
def job(sender=None):
color_picker._rgb = self.sideband.config["telemetry_fg"][0:3]
color_picker.ids.view_headline.on_tab_press()
Clock.schedule_once(job, 0)
def telemetry_fg_select(self, instance_color_picker: MDColorPicker, type_color: str, selected_color: Union[list, str]):
s = selected_color; color = [s[0], s[1], s[2], 1]
self.telemetry_screen.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
def telemetry_bg_color(self, sender=None):
color_picker = MDColorPicker(size_hint=(0.85, 0.85))
self.color_picker = color_picker
color_picker.open()
color_picker.bind(on_release=self.telemetry_bg_select)
def job(sender=None):
color_picker._rgb = self.sideband.config["telemetry_bg"][0:3]
color_picker.ids.view_headline.on_tab_press()
Clock.schedule_once(job, 0)
def telemetry_bg_select(self, instance_color_picker: MDColorPicker, type_color: str, selected_color: Union[list, str]):
s = selected_color; color = [s[0], s[1], s[2], 1]
self.telemetry_screen.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
def close_sub_telemetry_action(self, sender=None):
self.telemetry_action(direction="right")
### Icons Screen
######################################
def icons_action(self, sender=None):
if not self.root.ids.screen_manager.has_screen("icons_screen"):
self.icons_screen = Builder.load_string(layout_icons_screen)
self.icons_screen.app = self
self.root.ids.screen_manager.add_widget(self.icons_screen)
self.icons_filter()
self.root.ids.screen_manager.transition.direction = "left"
self.root.ids.screen_manager.current = "icons_screen"
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
def icons_selected(self, selected=None):
RNS.log("Selected: "+str(selected))
if selected == None:
selected = "alpha-p-circle-outline"
self.telemetry_set_icon(selected)
self.close_sub_telemetry_action()
def icons_filter(self, text="", search=False):
def add_icon_item(name_icon):
def select_factory(x):
def f():
self.icons_selected(x)
return f
self.icons_screen.ids.icons_rv.data.append(
{
"viewclass": "CustomOneLineIconListItem",
"icon": name_icon,
"text": name_icon,
"callback": lambda x: x,
"on_release": select_factory(name_icon)
}
)
self.icons_screen.ids.icons_rv.data = []
for name_icon in md_icons.keys():
if search:
if text in name_icon:
add_icon_item(name_icon)
else:
add_icon_item(name_icon)
### Map Screen ### Map Screen
###################################### ######################################

View File

@ -1001,590 +1001,6 @@ MDScreen:
id: map_layout id: map_layout
""" """
layout_telemetry_screen = """
MDScreen:
name: "telemetry_screen"
BoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "Telemetry"
anchor_title: "left"
elevation: 0
left_action_items:
[['menu', lambda x: root.app.nav_drawer.set_state("open")]]
right_action_items:
[
['close', lambda x: root.app.close_any_action(self)],
]
ScrollView:
id: telemetry_scrollview
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
padding: [dp(28), dp(48), dp(28), dp(16)]
MDLabel:
text: "Telemetry Over LXMF"
font_style: "H6"
MDLabel:
id: telemetry_info
markup: True
text: ""
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDLabel:
markup: True
text: "\\n\\n"
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDBoxLayout:
orientation: "vertical"
spacing: dp(24)
size_hint_y: None
padding: [dp(0),dp(24),dp(0),dp(0)]
height: dp(232)
MDRectangleFlatIconButton:
id: telemetry_send_update_button
icon: "upload-lock"
text: "Send Telemetry Update Now"
padding: [dp(0), dp(14), dp(0), dp(14)]
icon_size: dp(24)
font_size: dp(16)
size_hint: [1.0, None]
on_release: root.app.telemetry_send_update(self)
disabled: True
MDRectangleFlatIconButton:
id: telemetry_request_button
icon: "arrow-down-bold-hexagon-outline"
text: "Request Telemetry From Collector"
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.app.telemetry_request_action(self)
disabled: True
MDRectangleFlatIconButton:
id: telemetry_copy_button
icon: "content-copy"
text: "Copy Telemetry Data To Clipboard"
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.app.telemetry_copy(self)
disabled: False
MDRectangleFlatIconButton:
id: telemetry_own_button
icon: "database-eye-outline"
text: "Display Own 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.app.map_display_own_telemetry(self)
disabled: False
MDBoxLayout:
id: telemetry_enabled_fields
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
padding: [0, dp(16), 0, dp(0)]
MDTextField:
id: telemetry_collector
max_text_length: 32
hint_text: "Telemetry Collector LXMF Address"
text: ""
font_size: dp(24)
MDBoxLayout:
orientation: "horizontal"
padding: [0,0,dp(24),0]
size_hint_y: None
height: dp(48)
MDLabel:
id: telemetry_enabled_label
text: "Enable Telemetry"
font_style: "H6"
MDSwitch:
id: telemetry_enabled
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: "Automatically send to collector"
font_style: "H6"
MDSwitch:
id: telemetry_send_to_collector
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: "Only display from trusted"
font_style: "H6"
MDSwitch:
id: telemetry_display_trusted_only
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: "Send to all trusted peers"
font_style: "H6"
MDSwitch:
id: telemetry_send_to_trusted
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: "Send display style to everyone"
font_style: "H6"
MDSwitch:
id: telemetry_send_appearance
pos_hint: {"center_y": 0.3}
active: False
MDLabel:
markup: True
text: "\\n\\n"
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDLabel:
text: "Display Options"
font_style: "H6"
MDLabel:
id: telemetry_info4
markup: True
text: "\\nYou can customise the display style of your telemetry data when viewed by others, by setting an icon and color options. This is usually used by clients to display your telemetry entry on a map or in lists and overviews. If left unset, the receiver will decide how to display the data.\\n"
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
height: dp(112)
padding: [dp(0), dp(24), dp(0), dp(24)]
pos_hint: {"center_x": .5}
MDIconButton:
pos_hint: {"center_x": .5}
id: telemetry_icon_preview
icon: "account"
type: "large"
theme_icon_color: "Custom"
icon_color: [0, 0, 0, 1]
md_bg_color: [1, 1, 1, 1]
icon_size: dp(64)
size_hint_y: None
# width: dp(64)
height: dp(80)
on_release: root.app.icons_action(self)
MDRectangleFlatIconButton:
id: telemetry_icons_button
icon: "list-box-outline"
text: "Select From Available Icons"
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.app.icons_action(self)
disabled: False
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
padding: [dp(0),dp(24),dp(0),dp(0)]
height: dp(74)
MDBoxLayout:
orientation: "horizontal"
#size_hint_y: None
spacing: dp(24)
# padding: [0,0,dp(24),dp(0)]
# height: dp(48)
MDRectangleFlatIconButton:
id: telemetry_icons_button
icon: "list-box-outline"
text: "Set Foreground Color"
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.app.telemetry_fg_color(self)
disabled: False
MDRectangleFlatIconButton:
id: telemetry_icons_button
icon: "list-box-outline"
text: "Set Background Color"
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.app.telemetry_bg_color(self)
disabled: False
MDLabel:
markup: True
text: "\\n\\n\\n"
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDLabel:
text: "Sensor Types"
font_style: "H6"
MDLabel:
id: telemetry_info3
markup: True
text: ""
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Location"
font_style: "H6"
MDSwitch:
id: telemetry_s_location
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: "Battery State"
font_style: "H6"
MDSwitch:
id: telemetry_s_battery
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: "Pressure"
font_style: "H6"
MDSwitch:
id: telemetry_s_barometer
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: "Temperature"
font_style: "H6"
MDSwitch:
id: telemetry_s_temperature
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: "Humidity"
font_style: "H6"
MDSwitch:
id: telemetry_s_humidity
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: "Magnetic Field"
font_style: "H6"
MDSwitch:
id: telemetry_s_compass
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: "Ambient Light"
font_style: "H6"
MDSwitch:
id: telemetry_s_light
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: "Gravity"
font_style: "H6"
MDSwitch:
id: telemetry_s_gravity
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: "Angular Velocity"
font_style: "H6"
MDSwitch:
id: telemetry_s_gyroscope
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: "Acceleration"
font_style: "H6"
MDSwitch:
id: telemetry_s_accelerometer
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: "Proximity"
font_style: "H6"
MDSwitch:
id: telemetry_s_proximity
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: "Information"
font_style: "H6"
MDSwitch:
id: telemetry_s_information
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
id: telemetry_information_fields
orientation: "horizontal"
size_hint_y: None
spacing: dp(16)
height: dp(64)
padding: [0, dp(0), 0, dp(0)]
MDTextField:
id: telemetry_s_information_text
size_hint: [1.0, None]
hint_text: "Custom information text"
max_text_length: 256
text: ""
font_size: dp(24)
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"
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
"""
layout_icons_screen = """
MDScreen:
name: "icons_screen"
BoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "Available Icons"
anchor_title: "left"
elevation: 0
left_action_items:
[['menu', lambda x: root.app.nav_drawer.set_state("open")]]
right_action_items:
[
['close', lambda x: root.app.close_sub_telemetry_action(self)],
]
MDBoxLayout:
orientation: 'vertical'
spacing: dp(10)
padding: dp(20)
MDBoxLayout:
adaptive_height: True
MDIconButton:
icon: 'magnify'
MDTextField:
id: icons_search_field
hint_text: 'Search icon'
on_text: root.app.icons_filter(self.text, True)
RecycleView:
id: icons_rv
key_viewclass: 'viewclass'
key_size: 'height'
RecycleBoxLayout:
padding: dp(10)
default_size: None, dp(48)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
"""
layout_keys_screen = """ layout_keys_screen = """
MDScreen: MDScreen:
name: "keys_screen" name: "keys_screen"

View File

@ -40,7 +40,7 @@ class ObjectDetails():
self.delete_dialog = None self.delete_dialog = None
if not self.app.root.ids.screen_manager.has_screen("object_details_screen"): if not self.app.root.ids.screen_manager.has_screen("object_details_screen"):
self.screen = Builder.load_string(layou_object_details) self.screen = Builder.load_string(layout_object_details)
self.screen.app = self.app self.screen.app = self.app
self.screen.delegate = self self.screen.delegate = self
self.ids = self.screen.ids self.ids = self.screen.ids
@ -461,7 +461,7 @@ class RVDetails(MDRecycleView):
layou_object_details = """ layout_object_details = """
#:import MDLabel kivymd.uix.label.MDLabel #:import MDLabel kivymd.uix.label.MDLabel
#:import OneLineIconListItem kivymd.uix.list.OneLineIconListItem #:import OneLineIconListItem kivymd.uix.list.OneLineIconListItem
#:import Button kivy.uix.button.Button #:import Button kivy.uix.button.Button

952
sbapp/ui/telemetry.py Normal file
View File

@ -0,0 +1,952 @@
import time
import RNS
from typing import Union
from kivy.metrics import dp,sp
from kivy.lang.builder import Builder
from kivy.core.clipboard import Clipboard
from kivy.utils import escape_markup
from kivymd.uix.recycleview import MDRecycleView
from kivymd.uix.list import OneLineIconListItem
from kivymd.uix.pickers import MDColorPicker
from kivymd.icon_definitions import md_icons
from kivy.properties import StringProperty, BooleanProperty
from kivy.effects.scroll import ScrollEffect
from kivy.clock import Clock
from sideband.sense import Telemeter
import threading
from datetime import datetime
if RNS.vendor.platformutils.get_platform() == "android":
from ui.helpers import ts_format
else:
from .helpers import ts_format
class Telemetry():
def __init__(self, app):
self.app = app
self.screen = None
self.sensors_screen = None
self.icons_screen = None
self.color_picker = None
if not self.app.root.ids.screen_manager.has_screen("telemetry_screen"):
self.screen = Builder.load_string(layout_telemetry_screen)
self.screen.app = self.app
self.screen.delegate = self
self.app.root.ids.screen_manager.add_widget(self.screen)
self.screen.ids.telemetry_collector.bind(focus=self.telemetry_save)
if self.app.sideband.config["telemetry_collector"] == None:
self.screen.ids.telemetry_collector.text = ""
else:
self.screen.ids.telemetry_collector.text = RNS.hexrep(self.app.sideband.config["telemetry_collector"], delimit=False)
self.screen.ids.telemetry_icon_preview.icon_color = self.app.sideband.config["telemetry_fg"]
self.screen.ids.telemetry_icon_preview.md_bg_color = self.app.sideband.config["telemetry_bg"]
self.screen.ids.telemetry_icon_preview.icon = self.app.sideband.config["telemetry_icon"]
self.screen.ids.telemetry_enabled.active = self.app.sideband.config["telemetry_enabled"]
self.screen.ids.telemetry_enabled.bind(active=self.telemetry_enabled_toggle)
self.screen.ids.telemetry_send_to_collector.active = self.app.sideband.config["telemetry_send_to_collector"]
self.screen.ids.telemetry_send_to_collector.bind(active=self.telemetry_save)
self.screen.ids.telemetry_send_to_trusted.active = self.app.sideband.config["telemetry_send_to_trusted"]
self.screen.ids.telemetry_send_to_trusted.bind(active=self.telemetry_save)
self.screen.ids.telemetry_display_trusted_only.active = self.app.sideband.config["telemetry_display_trusted_only"]
self.screen.ids.telemetry_display_trusted_only.bind(active=self.telemetry_save)
self.screen.ids.telemetry_send_appearance.active = self.app.sideband.config["telemetry_send_appearance"]
self.screen.ids.telemetry_send_appearance.bind(active=self.telemetry_save)
self.screen.ids.telemetry_scrollview.effect_cls = ScrollEffect
info = "\nSideband allows you to securely share telemetry, such as location and sensor data, with people, custom programs, machines or other system over LXMF. You have complete control over what kind of telemetry to send, and who you share it with.\n\nTelemetry data is never sent to, via or processed by any external services or servers, but is carried exclusively within encrypted LXMF messages over Reticulum.\n\nWhen telemetry is enabled, it is possible to embed telemetry data in normal messages on a per-peer basis. You can control this from the [b]Conversations[/b] list, by selecting the [b]Edit[/b] option for the relevant peer.\n\nYou can also define a [b]Telemetry Collector[/b], that Sideband will automatically send telemetry to on a periodic basis - for example your Nomad Network home node.\n"
if self.app.theme_cls.theme_style == "Dark":
info = "[color=#"+self.app.dark_theme_text_color+"]"+info+"[/color]"
self.screen.ids.telemetry_info.text = info
def telemetry_enabled_toggle(self, sender=None, event=None):
self.telemetry_save()
if self.screen.ids.telemetry_enabled.active:
self.app.sideband.run_telemetry()
else:
self.app.sideband.stop_telemetry()
def telemetry_save(self, sender=None, event=None):
run_telemetry_update = False
if len(self.screen.ids.telemetry_collector.text) != 32:
self.screen.ids.telemetry_collector.text = ""
self.app.sideband.config["telemetry_collector"] = None
else:
try:
self.app.sideband.config["telemetry_collector"] = bytes.fromhex(self.screen.ids.telemetry_collector.text)
except:
self.screen.ids.telemetry_collector.text = ""
self.app.sideband.config["telemetry_collector"] = None
self.app.sideband.config["telemetry_enabled"] = self.screen.ids.telemetry_enabled.active
self.app.sideband.config["telemetry_send_to_collector"] = self.screen.ids.telemetry_send_to_collector.active
self.app.sideband.config["telemetry_send_to_trusted"] = self.screen.ids.telemetry_send_to_trusted.active
self.app.sideband.config["telemetry_display_trusted_only"] = self.screen.ids.telemetry_display_trusted_only.active
self.app.sideband.config["telemetry_send_appearance"] = self.screen.ids.telemetry_send_appearance.active
self.app.sideband.save_configuration()
if run_telemetry_update:
self.app.sideband.update_telemetry()
else:
self.app.sideband.setstate("app.flags.last_telemetry", time.time())
def converse_from_telemetry(self, sender=None):
if self.object_details_screen != None:
context_dest = self.object_details_screen.object_hash
if not self.object_details_screen.object_hash == self.app.sideband.lxmf_destination.hash:
self.open_conversation(context_dest)
def telemetry_copy(self, sender=None):
Clipboard.copy(str(self.app.sideband.get_telemetry()))
self.app.sideband.update_telemetry()
def telemetry_fg_color(self, sender=None):
if self.color_picker == None:
self.color_picker = MDColorPicker(size_hint=(0.85, 0.85))
self.color_picker.open()
self.color_picker.bind(on_release=self.telemetry_fg_select)
def job(sender=None):
self.color_picker._rgb = self.app.sideband.config["telemetry_fg"][0:3]
self.color_picker.ids.view_headline.on_tab_press()
Clock.schedule_once(job, 0)
def telemetry_fg_select(self, instance_color_picker: MDColorPicker, type_color: str, selected_color: Union[list, str]):
s = selected_color; color = [s[0], s[1], s[2], 1]
self.screen.ids.telemetry_icon_preview.icon_color = color
self.app.sideband.config["telemetry_fg"] = color
self.app.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
def telemetry_bg_color(self, sender=None):
if self.color_picker == None:
self.color_picker = MDColorPicker(size_hint=(0.85, 0.85))
self.color_picker.open()
self.color_picker.bind(on_release=self.telemetry_bg_select)
def job(sender=None):
self.color_picker._rgb = self.app.sideband.config["telemetry_bg"][0:3]
self.color_picker.ids.view_headline.on_tab_press()
Clock.schedule_once(job, 0)
def telemetry_bg_select(self, instance_color_picker: MDColorPicker, type_color: str, selected_color: Union[list, str]):
s = selected_color; color = [s[0], s[1], s[2], 1]
self.screen.ids.telemetry_icon_preview.md_bg_color = color
self.app.sideband.config["telemetry_bg"] = color
self.app.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
### Sensors Screen
######################################
def sensors_init(self):
if not self.app.root.ids.screen_manager.has_screen("sensors_screen"):
self.sensors_screen = Builder.load_string(layout_sensors_screen)
self.sensors_screen.app = self.app
self.sensors_screen.delegate = self
self.app.root.ids.screen_manager.add_widget(self.sensors_screen)
info3 = "\nTo include a specific type of telemetry data while sending, it must be enabled below. Please note that some sensor types are not supported on all devices. Sideband will only be able to read a specific type of sensor if your device actually includes hardware for it.\n"
if self.app.theme_cls.theme_style == "Dark":
info3 = "[color=#"+self.app.dark_theme_text_color+"]"+info3+"[/color]"
self.sensors_screen.ids.telemetry_info3.text = info3
try:
lat = self.app.sideband.config["telemetry_s_fixed_latlon"][0]; lon = self.app.sideband.config["telemetry_s_fixed_latlon"][1]
except:
lat = 0.0; lon = 0.0
self.sensors_screen.ids.telemetry_s_location.active = self.app.sideband.config["telemetry_s_location"]
self.sensors_screen.ids.telemetry_s_location.bind(active=self.telemetry_location_toggle)
self.sensors_screen.ids.telemetry_s_fixed_location.active = self.app.sideband.config["telemetry_s_fixed_location"]
self.sensors_screen.ids.telemetry_s_fixed_location.bind(active=self.telemetry_location_toggle)
self.sensors_screen.ids.telemetry_s_fixed_latlon.bind(focus=self.sensors_save)
self.sensors_screen.ids.telemetry_s_fixed_altitude.bind(focus=self.sensors_save)
self.sensors_screen.ids.telemetry_s_fixed_altitude.text = str(self.app.sideband.config["telemetry_s_fixed_altitude"])
self.sensors_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}"
self.sensors_screen.ids.telemetry_s_battery.active = self.app.sideband.config["telemetry_s_battery"]
self.sensors_screen.ids.telemetry_s_battery.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_barometer.active = self.app.sideband.config["telemetry_s_pressure"]
self.sensors_screen.ids.telemetry_s_barometer.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_temperature.active = self.app.sideband.config["telemetry_s_temperature"]
self.sensors_screen.ids.telemetry_s_temperature.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_humidity.active = self.app.sideband.config["telemetry_s_humidity"]
self.sensors_screen.ids.telemetry_s_humidity.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_compass.active = self.app.sideband.config["telemetry_s_magnetic_field"]
self.sensors_screen.ids.telemetry_s_compass.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_light.active = self.app.sideband.config["telemetry_s_ambient_light"]
self.sensors_screen.ids.telemetry_s_light.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_gravity.active = self.app.sideband.config["telemetry_s_gravity"]
self.sensors_screen.ids.telemetry_s_gravity.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_gyroscope.active = self.app.sideband.config["telemetry_s_angular_velocity"]
self.sensors_screen.ids.telemetry_s_gyroscope.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_accelerometer.active = self.app.sideband.config["telemetry_s_acceleration"]
self.sensors_screen.ids.telemetry_s_accelerometer.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_proximity.active = self.app.sideband.config["telemetry_s_proximity"]
self.sensors_screen.ids.telemetry_s_proximity.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_information.active = self.app.sideband.config["telemetry_s_information"]
self.sensors_screen.ids.telemetry_s_information.bind(active=self.sensors_save)
self.sensors_screen.ids.telemetry_s_information_text.text = str(self.app.sideband.config["telemetry_s_information_text"])
self.sensors_screen.ids.telemetry_s_information_text.bind(focus=self.sensors_save)
def sensors_action(self, sender=None):
self.sensors_init()
self.app.root.ids.screen_manager.transition.direction = "left"
self.app.root.ids.screen_manager.current = "sensors_screen"
self.app.root.ids.nav_drawer.set_state("closed")
self.app.sideband.setstate("app.displaying", self.app.root.ids.screen_manager.current)
def telemetry_location_toggle(self, sender=None, event=None):
if sender == self.sensors_screen.ids.telemetry_s_location:
if self.sensors_screen.ids.telemetry_s_location.active:
self.sensors_screen.ids.telemetry_s_fixed_location.active = False
if sender == self.sensors_screen.ids.telemetry_s_fixed_location:
if self.sensors_screen.ids.telemetry_s_fixed_location.active:
self.sensors_screen.ids.telemetry_s_location.active = False
if self.sensors_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"):
RNS.log("Requesting location permission", RNS.LOG_DEBUG)
request_permissions(["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])
self.sensors_save()
def sensors_save(self, sender=None, event=None):
run_telemetry_update = False
self.app.sideband.config["telemetry_s_location"] = self.sensors_screen.ids.telemetry_s_location.active
self.app.sideband.config["telemetry_s_fixed_location"] = self.sensors_screen.ids.telemetry_s_fixed_location.active
self.app.sideband.config["telemetry_s_battery"] = self.sensors_screen.ids.telemetry_s_battery.active
self.app.sideband.config["telemetry_s_pressure"] = self.sensors_screen.ids.telemetry_s_barometer.active
self.app.sideband.config["telemetry_s_temperature"] = self.sensors_screen.ids.telemetry_s_temperature.active
self.app.sideband.config["telemetry_s_humidity"] = self.sensors_screen.ids.telemetry_s_humidity.active
self.app.sideband.config["telemetry_s_magnetic_field"] = self.sensors_screen.ids.telemetry_s_compass.active
self.app.sideband.config["telemetry_s_ambient_light"] = self.sensors_screen.ids.telemetry_s_light.active
self.app.sideband.config["telemetry_s_gravity"] = self.sensors_screen.ids.telemetry_s_gravity.active
self.app.sideband.config["telemetry_s_angular_velocity"] = self.sensors_screen.ids.telemetry_s_gyroscope.active
self.app.sideband.config["telemetry_s_acceleration"] = self.sensors_screen.ids.telemetry_s_accelerometer.active
self.app.sideband.config["telemetry_s_proximity"] = self.sensors_screen.ids.telemetry_s_proximity.active
if self.app.sideband.config["telemetry_s_information"] != self.sensors_screen.ids.telemetry_s_information.active:
self.app.sideband.config["telemetry_s_information"] = self.sensors_screen.ids.telemetry_s_information.active
run_telemetry_update = True
if self.app.sideband.config["telemetry_s_information_text"] != self.sensors_screen.ids.telemetry_s_information_text.text:
self.app.sideband.config["telemetry_s_information_text"] = self.sensors_screen.ids.telemetry_s_information_text.text
run_telemetry_update = True
try:
alt = float(self.sensors_screen.ids.telemetry_s_fixed_altitude.text.strip().replace(" ", ""))
self.sensors_screen.ids.telemetry_s_fixed_altitude.text = str(alt)
if self.app.sideband.config["telemetry_s_fixed_altitude"] != alt:
self.app.sideband.config["telemetry_s_fixed_altitude"] = alt
run_telemetry_update = True
except:
self.sensors_screen.ids.telemetry_s_fixed_altitude.text = str(self.app.sideband.config["telemetry_s_fixed_altitude"])
try:
s = self.sensors_screen.ids.telemetry_s_fixed_latlon.text
l = s.strip().replace(" ","").split(",")
lat = float(l[0]); lon = float(l[1])
if self.app.sideband.config["telemetry_s_fixed_latlon"] != [lat, lon]:
run_telemetry_update = True
self.app.sideband.config["telemetry_s_fixed_latlon"] = [lat, lon]
self.sensors_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}"
except:
try:
lat = self.app.sideband.config["telemetry_s_fixed_latlon"][0]
lon = self.app.sideband.config["telemetry_s_fixed_latlon"][1]
self.sensors_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}"
except:
self.app.sideband.config["telemetry_s_fixed_latlon"] = [0.0, 0.0]
self.sensors_screen.ids.telemetry_s_fixed_latlon.text = "0.0, 0.0"
self.app.sideband.save_configuration()
if run_telemetry_update:
self.app.sideband.update_telemetry()
else:
self.app.sideband.setstate("app.flags.last_telemetry", time.time())
### Icons Screen
######################################
def icons_action(self, sender=None):
if not self.app.root.ids.screen_manager.has_screen("icons_screen"):
self.icons_screen = Builder.load_string(layout_icons_screen)
self.icons_screen.app = self.app
self.icons_screen.delegate = self
self.app.root.ids.screen_manager.add_widget(self.icons_screen)
self.icons_filter()
self.app.root.ids.screen_manager.transition.direction = "left"
self.app.root.ids.screen_manager.current = "icons_screen"
self.app.sideband.setstate("app.displaying", self.app.root.ids.screen_manager.current)
# sf = self.icons_screen.ids.icons_search_field.text
# self.icons_filter(sf, len(sf)>0)
def telemetry_set_icon(self, text="", search=False):
if text in md_icons.keys():
self.screen.ids.telemetry_icon_preview.icon = text
else:
self.screen.ids.telemetry_icon_preview.icon = "alpha-p-circle-outline"
self.app.sideband.config["telemetry_icon"] = self.screen.ids.telemetry_icon_preview.icon
self.app.sideband.save_configuration()
self.own_appearance_changed = True
def icons_selected(self, selected=None):
RNS.log("Selected: "+str(selected))
if selected == None:
selected = "alpha-p-circle-outline"
self.telemetry_set_icon(selected)
self.app.close_sub_telemetry_action()
def icons_filter(self, text="", search=False):
def add_icon_item(name_icon):
def select_factory(x):
def f():
self.icons_selected(x)
return f
self.icons_screen.ids.icons_rv.data.append(
{
"viewclass": "CustomOneLineIconListItem",
"icon": name_icon,
"text": name_icon,
"callback": lambda x: x,
"on_release": select_factory(name_icon)
}
)
self.icons_screen.ids.icons_rv.data = []
for name_icon in md_icons.keys():
if search:
if text in name_icon:
add_icon_item(name_icon)
else:
add_icon_item(name_icon)
layout_telemetry_screen = """
MDScreen:
name: "telemetry_screen"
BoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "Telemetry"
anchor_title: "left"
elevation: 0
left_action_items:
[['menu', lambda x: root.app.nav_drawer.set_state("open")]]
right_action_items:
[
['close', lambda x: root.app.close_any_action(self)],
]
ScrollView:
id: telemetry_scrollview
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
padding: [dp(28), dp(48), dp(28), dp(16)]
MDLabel:
text: "Telemetry Over LXMF"
font_style: "H6"
MDLabel:
id: telemetry_info
markup: True
text: ""
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
padding: [0, dp(0), 0, dp(0)]
MDTextField:
id: telemetry_collector
max_text_length: 32
hint_text: "Telemetry Collector LXMF Address"
text: ""
font_size: dp(24)
MDBoxLayout:
orientation: "horizontal"
padding: [0,0,dp(24),0]
size_hint_y: None
height: dp(48)
MDLabel:
id: telemetry_enabled_label
text: "Enable Telemetry"
font_style: "H6"
MDSwitch:
id: telemetry_enabled
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: "Automatically send to collector"
font_style: "H6"
MDSwitch:
id: telemetry_send_to_collector
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: "Only display from trusted"
font_style: "H6"
MDSwitch:
id: telemetry_display_trusted_only
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: "Send to all trusted peers"
font_style: "H6"
MDSwitch:
id: telemetry_send_to_trusted
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: "Send display style to everyone"
font_style: "H6"
MDSwitch:
id: telemetry_send_appearance
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "vertical"
spacing: dp(24)
size_hint_y: None
padding: [dp(0),dp(24),dp(0),dp(60)]
#height: dp(232)
height: self.minimum_height
MDRectangleFlatIconButton:
id: telemetry_sensors_button
icon: "sun-thermometer-outline"
text: "Configure Sensors"
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.sensors_action(self)
disabled: False
MDRectangleFlatIconButton:
id: telemetry_own_button
icon: "database-eye-outline"
text: "Display Own 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.app.map_display_own_telemetry(self)
disabled: False
MDRectangleFlatIconButton:
id: telemetry_copy_button
icon: "content-copy"
text: "Copy Telemetry Data To Clipboard"
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.telemetry_copy(self)
disabled: False
MDRectangleFlatIconButton:
id: telemetry_send_update_button
icon: "upload-lock"
text: "Send Telemetry To Collector"
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.app.telemetry_send_update(self)
disabled: True
MDRectangleFlatIconButton:
id: telemetry_request_button
icon: "arrow-down-bold-hexagon-outline"
text: "Request Telemetry From Collector"
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.app.telemetry_request_action(self)
disabled: True
MDLabel:
text: "Display Options"
font_style: "H6"
MDLabel:
id: telemetry_info4
markup: True
text: "\\nYou can customise the display style of your telemetry data when viewed by others, by setting an icon and color options. This is usually used by clients to display your telemetry entry on a map or in lists and overviews. If left unset, the receiver will decide how to display the data.\\n"
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
height: dp(112)
padding: [dp(0), dp(24), dp(0), dp(24)]
pos_hint: {"center_x": .5}
MDIconButton:
pos_hint: {"center_x": .5}
id: telemetry_icon_preview
icon: "account"
type: "large"
theme_icon_color: "Custom"
icon_color: [0, 0, 0, 1]
md_bg_color: [1, 1, 1, 1]
icon_size: dp(64)
size_hint_y: None
# width: dp(64)
height: dp(80)
on_release: root.delegate.icons_action(self)
MDRectangleFlatIconButton:
id: telemetry_icons_button
icon: "list-box-outline"
text: "Select From Available Icons"
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.icons_action(self)
disabled: False
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
padding: [dp(0),dp(24),dp(0),dp(12)]
height: dp(74)
MDBoxLayout:
orientation: "horizontal"
#size_hint_y: None
spacing: dp(24)
# padding: [0,0,dp(24),dp(0)]
# height: dp(48)
MDRectangleFlatIconButton:
id: telemetry_icons_button
icon: "list-box-outline"
text: "Set Foreground Color"
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.telemetry_fg_color(self)
disabled: False
MDRectangleFlatIconButton:
id: telemetry_icons_button
icon: "list-box-outline"
text: "Set Background Color"
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.telemetry_bg_color(self)
disabled: False
"""
layout_sensors_screen = """
MDScreen:
name: "sensors_screen"
BoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "Sensors"
anchor_title: "left"
elevation: 0
left_action_items:
[['menu', lambda x: root.app.nav_drawer.set_state("open")]]
right_action_items:
[
['close', lambda x: root.app.close_sub_telemetry_action(self)],
]
ScrollView:
id: sensors_scrollview
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
padding: [dp(28), dp(48), dp(28), dp(16)]
MDLabel:
text: "Sensor Types"
font_style: "H6"
MDLabel:
id: telemetry_info3
markup: True
text: ""
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Location"
font_style: "H6"
MDSwitch:
id: telemetry_s_location
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: "Battery State"
font_style: "H6"
MDSwitch:
id: telemetry_s_battery
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: "Pressure"
font_style: "H6"
MDSwitch:
id: telemetry_s_barometer
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: "Temperature"
font_style: "H6"
MDSwitch:
id: telemetry_s_temperature
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: "Humidity"
font_style: "H6"
MDSwitch:
id: telemetry_s_humidity
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: "Magnetic Field"
font_style: "H6"
MDSwitch:
id: telemetry_s_compass
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: "Ambient Light"
font_style: "H6"
MDSwitch:
id: telemetry_s_light
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: "Gravity"
font_style: "H6"
MDSwitch:
id: telemetry_s_gravity
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: "Angular Velocity"
font_style: "H6"
MDSwitch:
id: telemetry_s_gyroscope
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: "Acceleration"
font_style: "H6"
MDSwitch:
id: telemetry_s_accelerometer
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: "Proximity"
font_style: "H6"
MDSwitch:
id: telemetry_s_proximity
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: "Information"
font_style: "H6"
MDSwitch:
id: telemetry_s_information
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
id: telemetry_information_fields
orientation: "horizontal"
size_hint_y: None
spacing: dp(16)
height: dp(64)
padding: [0, dp(0), 0, dp(0)]
MDTextField:
id: telemetry_s_information_text
size_hint: [1.0, None]
hint_text: "Custom information text"
max_text_length: 256
text: ""
font_size: dp(24)
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"
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
"""
layout_icons_screen = """
MDScreen:
name: "icons_screen"
BoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "Available Icons"
anchor_title: "left"
elevation: 0
left_action_items:
[['menu', lambda x: root.app.nav_drawer.set_state("open")]]
right_action_items:
[
['close', lambda x: root.app.close_sub_telemetry_action(self)],
]
MDBoxLayout:
orientation: 'vertical'
spacing: dp(10)
padding: dp(20)
MDBoxLayout:
adaptive_height: True
MDIconButton:
icon: 'magnify'
MDTextField:
id: icons_search_field
hint_text: 'Search icon'
on_text: root.delegate.icons_filter(self.text, True)
RecycleView:
id: icons_rv
key_viewclass: 'viewclass'
key_size: 'height'
RecycleBoxLayout:
padding: dp(10)
default_size: None, dp(48)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
"""