from openpilot.common.params import Params from openpilot.selfdrive.ui.widgets.ssh_key import ssh_key_item from openpilot.selfdrive.ui.ui_state import ui_state from openpilot.system.hardware.tici.usb_storage import apply_usb_storage_state from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets.list_view import toggle_item from openpilot.system.ui.widgets.scroller_tici import Scroller from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.multilang import tr, tr_noop if gui_app.iqpilot_ui(): from openpilot.system.ui.iqpilot.widgets.list_view import toggle_item # Description constants DESCRIPTIONS = { 'enable_adb': tr_noop( "ADB (Android Debug Bridge) allows connecting to your device over USB or over the network." ), 'ssh_key': tr_noop( "Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username " + "other than your own. An IQ.Pilot employee will NEVER ask you to add their GitHub username." ), 'usb_storage': tr_noop( "Exposes a snapshot of recent dashcam clips and logs as a USB drive when connected to a computer. " + "IQ.Pilot keeps running while this is enabled." ), } class DeveloperLayout(Widget): def __init__(self): super().__init__() self._params = Params() self._is_release = self._params.get_bool("IsReleaseBranch") # Build items and keep references for callbacks/state updates self._adb_toggle = toggle_item( lambda: tr("Enable ADB"), description=lambda: tr(DESCRIPTIONS["enable_adb"]), initial_state=self._params.get_bool("AdbEnabled"), callback=self._on_enable_adb, enabled=ui_state.is_offroad, ) self._usb_storage_toggle = toggle_item( lambda: tr("USB Storage"), description=lambda: tr(DESCRIPTIONS["usb_storage"]), initial_state=self._params.get_bool("UsbStorageEnabled"), callback=self._on_enable_usb_storage, enabled=ui_state.is_offroad, ) # SSH enable toggle + SSH key management self._ssh_toggle = toggle_item( lambda: tr("Enable SSH"), description="", initial_state=self._params.get_bool("SshEnabled"), callback=self._on_enable_ssh, ) self._ssh_keys = ssh_key_item(lambda: tr("SSH Keys"), description=lambda: tr(DESCRIPTIONS["ssh_key"])) self._on_enable_ui_debug(self._params.get_bool("ShowDebugInfo")) self._scroller = Scroller([ self._adb_toggle, self._usb_storage_toggle, self._ssh_toggle, self._ssh_keys, ], line_separator=True, spacing=0) # Toggles should be not available to change in onroad state ui_state.add_offroad_transition_callback(self._update_toggles) def _render(self, rect): self._scroller.render(rect) def show_event(self): self._scroller.show_event() self._update_toggles() def _update_toggles(self): ui_state.update_params() # TODO: make a param control list item so we don't need to manage internal state as much here # refresh toggles from params to mirror external changes for key, item in ( ("AdbEnabled", self._adb_toggle), ("UsbStorageEnabled", self._usb_storage_toggle), ("SshEnabled", self._ssh_toggle), ): item.action_item.set_state(self._params.get_bool(key)) def _on_enable_ui_debug(self, state: bool): self._params.put_bool("ShowDebugInfo", state) gui_app.set_show_touches(state) gui_app.set_show_fps(state) gui_app.set_show_mouse_coords(state) def _on_enable_adb(self, state: bool): self._params.put_bool("AdbEnabled", state) def _on_enable_usb_storage(self, state: bool): apply_usb_storage_state(state) def _on_enable_ssh(self, state: bool): self._params.put_bool("SshEnabled", state) def _on_long_maneuver_mode(self, state: bool): self._params.put_bool("LongitudinalManeuverMode", state) self._params.put_bool("JoystickDebugMode", False) def _on_lat_maneuver_mode(self, state: bool): self._params.put_bool("LateralManeuverMode", state) self._params.put_bool("JoystickDebugMode", False)