diff --git a/sbapp/main.py b/sbapp/main.py index fdc1f8e..0159629 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -52,9 +52,7 @@ if RNS.vendor.platformutils.get_platform() != "android": local = os.path.dirname(__file__) sys.path.append(local) -from typing import Union from kivymd.app import MDApp -from kivymd.icon_definitions import md_icons from kivy.core.window import Window from kivy.core.clipboard import Clipboard from kivy.base import EventLoop @@ -65,7 +63,6 @@ from kivy.uix.screenmanager import ScreenManager 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 kivymd.uix.filemanager import MDFileManager from kivymd.toast import toast @@ -82,6 +79,7 @@ if RNS.vendor.platformutils.get_platform() == "android": from ui.layouts import * from ui.conversations import Conversations, MsgSync, NewConv + from ui.telemetry import Telemetry from ui.objectdetails import ObjectDetails from ui.announces import Announces from ui.messages import Messages, ts_format, messages_screen_kv @@ -102,6 +100,7 @@ else: from .ui.layouts import * from .ui.conversations import Conversations, MsgSync, NewConv from .ui.announces import Announces + from .ui.telemetry import Telemetry from .ui.objectdetails import ObjectDetails from .ui.messages import Messages, ts_format, messages_screen_kv 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.set_ui_theme() + self.dark_theme_text_color = dark_theme_text_color self.conversations_view = None self.messages_view = None self.map = None self.map_layer = None self.map_screen = None + self.telemetry_screen = None self.map_cache = self.sideband.map_cache self.offline_source = None self.map_settings_screen = None @@ -794,6 +795,10 @@ class SidebandApp(MDApp): self.close_sub_map_action() elif self.root.ids.screen_manager.current == "object_details_screen": 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: self.open_conversations(direction="right") @@ -876,6 +881,10 @@ class SidebandApp(MDApp): self.object_details_screen.close_action() elif self.root.ids.screen_manager.current == "map_settings_screen": 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: self.open_conversations(direction="right") @@ -3063,222 +3072,19 @@ class SidebandApp(MDApp): def telemetry_init(self): if not self.telemetry_ready: - if not self.root.ids.screen_manager.has_screen("telemetry_screen"): - 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_screen = Telemetry(self) 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"): 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.current = "telemetry_screen" self.root.ids.nav_drawer.set_state("closed") self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current) - 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.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 close_sub_telemetry_action(self, sender=None): + self.telemetry_action(direction="right") + def telemetry_send_update(self, sender=None): # TODO: Implement pass @@ -3287,98 +3093,6 @@ class SidebandApp(MDApp): # TODO: Implement 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 ###################################### diff --git a/sbapp/ui/layouts.py b/sbapp/ui/layouts.py index f4b58eb..5aa3cd8 100644 --- a/sbapp/ui/layouts.py +++ b/sbapp/ui/layouts.py @@ -1001,590 +1001,6 @@ MDScreen: 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 = """ MDScreen: name: "keys_screen" diff --git a/sbapp/ui/objectdetails.py b/sbapp/ui/objectdetails.py index 34838db..8735915 100644 --- a/sbapp/ui/objectdetails.py +++ b/sbapp/ui/objectdetails.py @@ -40,7 +40,7 @@ class ObjectDetails(): self.delete_dialog = None 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.delegate = self 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 OneLineIconListItem kivymd.uix.list.OneLineIconListItem #:import Button kivy.uix.button.Button diff --git a/sbapp/ui/telemetry.py b/sbapp/ui/telemetry.py new file mode 100644 index 0000000..be4fcaa --- /dev/null +++ b/sbapp/ui/telemetry.py @@ -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' +""" \ No newline at end of file