diff --git a/selfdrive/ui/layouts/settings/developer.py b/selfdrive/ui/layouts/settings/developer.py index 5f904485c2..2ff94aa52d 100644 --- a/selfdrive/ui/layouts/settings/developer.py +++ b/selfdrive/ui/layouts/settings/developer.py @@ -1,3 +1,4 @@ +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.ui.widgets import Widget @@ -34,7 +35,7 @@ DESCRIPTIONS = { class DeveloperLayout(Widget): def __init__(self): super().__init__() - self._params = ui_state.params + self._params = Params() self._is_release = self._params.get_bool("IsReleaseBranch") # Build items and keep references for callbacks/state updates diff --git a/selfdrive/ui/layouts/settings/device.py b/selfdrive/ui/layouts/settings/device.py index b932647b04..8830ef946f 100644 --- a/selfdrive/ui/layouts/settings/device.py +++ b/selfdrive/ui/layouts/settings/device.py @@ -3,6 +3,7 @@ import math from cereal import messaging, log from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params from openpilot.common.swaglog import cloudlog from openpilot.selfdrive.ui.onroad.driver_camera_dialog import DriverCameraDialog from openpilot.selfdrive.ui.ui_state import ui_state @@ -34,7 +35,7 @@ class DeviceLayout(Widget): def __init__(self): super().__init__() - self._params = ui_state.params + self._params = Params() self._select_language_dialog: MultiOptionDialog | None = None self._driver_camera: DriverCameraDialog | None = None self._pair_device_dialog: PairingDialog | None = None diff --git a/selfdrive/ui/layouts/settings/toggles.py b/selfdrive/ui/layouts/settings/toggles.py index 2d118e7e1b..f5f3a4e9c5 100644 --- a/selfdrive/ui/layouts/settings/toggles.py +++ b/selfdrive/ui/layouts/settings/toggles.py @@ -1,5 +1,5 @@ from cereal import log -from openpilot.common.params import UnknownKeyName +from openpilot.common.params import Params, UnknownKeyName from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets.list_view import multiple_button_item, toggle_item from openpilot.system.ui.widgets.scroller_tici import Scroller @@ -41,7 +41,7 @@ DESCRIPTIONS = { class TogglesLayout(Widget): def __init__(self): super().__init__() - self._params = ui_state.params + self._params = Params() self._is_release = self._params.get_bool("IsReleaseBranch") # param, title, desc, icon, needs_restart @@ -198,6 +198,11 @@ class TogglesLayout(Widget): self._update_experimental_mode_icon() + # 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 param in self._toggle_defs: + self._toggles[param].action_item.set_state(self._params.get_bool(param)) + # these toggles need restart, block while engaged for toggle_def in self._toggle_defs: if self._toggle_defs[toggle_def][3] and toggle_def not in self._locked_toggles: diff --git a/selfdrive/ui/sunnypilot/layouts/settings/models.py b/selfdrive/ui/sunnypilot/layouts/settings/models.py index d2ae664ceb..43f0d25b47 100644 --- a/selfdrive/ui/sunnypilot/layouts/settings/models.py +++ b/selfdrive/ui/sunnypilot/layouts/settings/models.py @@ -230,7 +230,9 @@ class ModelsLayout(Widget): turn_desire: bool = ui_state.params.get_bool("LaneTurnDesire") live_delay: bool = ui_state.params.get_bool("LagdToggle") + self.lane_turn_desire_toggle.action_item.set_state(turn_desire) self.lane_turn_value_control.set_visible(turn_desire and advanced_controls) + self.lagd_toggle.action_item.set_state(live_delay) self.delay_control.set_visible(not live_delay and advanced_controls) new_step = int(round(100 / CV.MPH_TO_KPH)) if ui_state.is_metric else 100 if self.lane_turn_value_control.action_item.value_change_step != new_step: diff --git a/selfdrive/ui/sunnypilot/layouts/settings/settings.py b/selfdrive/ui/sunnypilot/layouts/settings/settings.py index b2f7ceb41d..45c9b93483 100644 --- a/selfdrive/ui/sunnypilot/layouts/settings/settings.py +++ b/selfdrive/ui/sunnypilot/layouts/settings/settings.py @@ -31,7 +31,6 @@ from openpilot.selfdrive.ui.sunnypilot.layouts.settings.steering import Steering from openpilot.selfdrive.ui.sunnypilot.layouts.settings.cruise import CruiseLayout from openpilot.selfdrive.ui.sunnypilot.layouts.settings.visuals import VisualsLayout from openpilot.selfdrive.ui.sunnypilot.layouts.settings.display import DisplayLayout -from openpilot.selfdrive.ui.ui_state import ui_state # from openpilot.selfdrive.ui.sunnypilot.layouts.settings.navigation import NavigationLayout @@ -197,10 +196,6 @@ class SettingsLayoutSP(OP.SettingsLayout): return False - def set_current_panel(self, panel_type: OP.PanelType): - super().set_current_panel(panel_type) - ui_state.set_active_layout(self._panels[self._current_panel].instance) - def show_event(self): super().show_event() self._panels[self._current_panel].instance.show_event() diff --git a/selfdrive/ui/sunnypilot/layouts/settings/sunnylink.py b/selfdrive/ui/sunnypilot/layouts/settings/sunnylink.py index 20a8983c5a..316d4d2240 100644 --- a/selfdrive/ui/sunnypilot/layouts/settings/sunnylink.py +++ b/selfdrive/ui/sunnypilot/layouts/settings/sunnylink.py @@ -320,6 +320,7 @@ class SunnylinkLayout(Widget): self._sunnylink_enabled = ui_state.params.get_bool("SunnylinkEnabled") self._sunnylink_toggle.set_right_value(tr("Dongle ID") + ": " + self._get_sunnylink_dongle_id()) self._sunnylink_toggle.action_item.set_enabled(not ui_state.is_onroad()) + self._sunnylink_toggle.action_item.set_state(self._sunnylink_enabled) self._sunnylink_uploader_toggle.action_item.set_enabled(self._sunnylink_enabled) self.handle_backup_restore_progress() diff --git a/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/hyundai.py b/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/hyundai.py index 2c391a4b02..f6849eb201 100644 --- a/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/hyundai.py +++ b/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/hyundai.py @@ -55,4 +55,5 @@ class HyundaiSettings(BrandSettings): self.longitudinal_tuning_item.action_item.set_enabled(not longitudinal_tuning_disabled) self.longitudinal_tuning_item.set_description(long_tuning_desc) self.longitudinal_tuning_item.show_description(True) + self.longitudinal_tuning_item.action_item.set_selected_button(tuning_param) self.longitudinal_tuning_item.set_visible(self.alpha_long_available) diff --git a/selfdrive/ui/sunnypilot/ui_helpers.py b/selfdrive/ui/sunnypilot/ui_helpers.py deleted file mode 100644 index 798c920950..0000000000 --- a/selfdrive/ui/sunnypilot/ui_helpers.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. - -This file is part of sunnypilot and is licensed under the MIT License. -See the LICENSE.md file in the root directory for more details. -""" - - -@staticmethod -def update_item_from_param(item, key, params): - if not (action := getattr(item, 'action_item', None)): - return - - if hasattr(action, 'set_state'): - action.set_state(params.get_bool(key)) - elif hasattr(action, 'set_value'): - action.set_value(params.get(key, return_default=True)) - else: - try: - val = int(params.get(key, return_default=True)) - if hasattr(action, 'selected_button'): - action.selected_button = val - if hasattr(action, 'current_value'): - action.current_value = val - except (ValueError, TypeError): - pass - - -@staticmethod -def sync_layout_params(layout, param_name, params): - targets = [] - if toggles := getattr(layout, '_toggles', None): - targets.extend([(item, k) for k, item in toggles.items()]) - - items = getattr(layout, 'items', []) or getattr(getattr(layout, '_scroller', None), '_items', []) - for item in items: - action = getattr(item, 'action_item', None) - if key := getattr(action, 'param_key', None) or getattr(getattr(action, 'toggle', None), 'param_key', None): - targets.append((item, key)) - - for item, key in targets: - if param_name is None or key == param_name: - update_item_from_param(item, key, params) diff --git a/selfdrive/ui/sunnypilot/ui_state.py b/selfdrive/ui/sunnypilot/ui_state.py index b24ab8c62b..af625ee619 100644 --- a/selfdrive/ui/sunnypilot/ui_state.py +++ b/selfdrive/ui/sunnypilot/ui_state.py @@ -5,49 +5,23 @@ This file is part of sunnypilot and is licensed under the MIT License. See the LICENSE.md file in the root directory for more details. """ from cereal import messaging, custom -from openpilot.common.swaglog import cloudlog - -from openpilot.sunnypilot.common.param_watcher import ParamWatcher +from openpilot.common.params import Params from openpilot.sunnypilot.sunnylink.sunnylink_state import SunnylinkState -from openpilot.selfdrive.ui.sunnypilot.ui_helpers import sync_layout_params class UIStateSP: def __init__(self): - self.params = ParamWatcher() - self.params.add_watcher(self.on_param_change) - self.params.start() + self.params = Params() self.sm_services_ext = [ "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP", "gpsLocation", "liveTorqueParameters", "carStateSP", "liveMapDataSP", "carParamsSP", "liveDelay" ] self.sunnylink_state = SunnylinkState() - self.active_layout = None - self.changed_params = set() - - def set_active_layout(self, layout): - self.active_layout = layout - if layout: - sync_layout_params(layout, None, self.params) - - def on_param_change(self, param_name, mask): - self.changed_params.add(param_name) def update(self) -> None: self.sunnylink_state.start() - if not self.params.is_watching(): - cloudlog.warning("ParamWatcher thread died, restarting...") - self.params.start() - - if self.changed_params: - while self.changed_params: - self.changed_params.pop() - - if self.active_layout: - sync_layout_params(self.active_layout, None, self.params) - def update_params(self) -> None: CP_SP_bytes = self.params.get("CarParamsSPPersistent") if CP_SP_bytes is not None: diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py index f7b914f709..c78fdccb59 100644 --- a/selfdrive/ui/ui_state.py +++ b/selfdrive/ui/ui_state.py @@ -6,6 +6,7 @@ from collections.abc import Callable from enum import Enum from cereal import messaging, car, log from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.params import Params from openpilot.common.swaglog import cloudlog from openpilot.selfdrive.ui.lib.prime_state import PrimeState from openpilot.system.ui.lib.application import gui_app @@ -33,6 +34,7 @@ class UIState(UIStateSP): def _initialize(self): UIStateSP.__init__(self) + self.params = Params() self.sm = messaging.SubMaster( [ "modelV2", diff --git a/system/ui/sunnypilot/widgets/list_view.py b/system/ui/sunnypilot/widgets/list_view.py index 09a0ce0d8d..ac646df5bf 100644 --- a/system/ui/sunnypilot/widgets/list_view.py +++ b/system/ui/sunnypilot/widgets/list_view.py @@ -16,7 +16,6 @@ from openpilot.system.ui.widgets.list_view import ListItem, ToggleAction, ItemAc _resolve_value, BUTTON_WIDTH, BUTTON_HEIGHT, TEXT_PADDING from openpilot.system.ui.sunnypilot.lib.styles import style from openpilot.system.ui.sunnypilot.widgets.option_control import OptionControlSP, LABEL_WIDTH -from openpilot.selfdrive.ui.ui_state import ui_state class ToggleActionSP(ToggleAction): @@ -248,9 +247,6 @@ class ListItemSP(ListItem): def toggle_item_sp(title: str | Callable[[], str], description: str | Callable[[], str] | None = None, initial_state: bool = False, callback: Callable | None = None, icon: str = "", enabled: bool | Callable[[], bool] = True, param: str | None = None) -> ListItemSP: - if param is None and hasattr(ui_state.params, 'last_accessed_param') and ui_state.params.last_accessed_param: - param = ui_state.params.last_accessed_param - ui_state.params.last_accessed_param = None action = ToggleActionSP(initial_state=initial_state, enabled=enabled, callback=callback, param=param) return ListItemSP(title=title, description=description, action_item=action, icon=icon, callback=callback) @@ -258,9 +254,6 @@ def toggle_item_sp(title: str | Callable[[], str], description: str | Callable[[ def multiple_button_item_sp(title: str | Callable[[], str], description: str | Callable[[], str], buttons: list[str | Callable[[], str]], selected_index: int = 0, button_width: int = style.BUTTON_WIDTH, callback: Callable = None, icon: str = "", param: str | None = None, inline: bool = False) -> ListItemSP: - if param is None and hasattr(ui_state.params, 'last_accessed_param') and ui_state.params.last_accessed_param: - param = ui_state.params.last_accessed_param - ui_state.params.last_accessed_param = None action = MultipleButtonActionSP(buttons, button_width, selected_index, callback=callback, param=param) return ListItemSP(title=title, description=description, icon=icon, action_item=action, inline=inline)