Big UI: Not your Papaw's Cached Params

This commit is contained in:
firestarsdog
2026-07-27 12:46:49 -04:00
committed by whoisdomi
parent 43fb2f827f
commit 2542d448f9
6 changed files with 53 additions and 11 deletions
+1 -2
View File
@@ -1,6 +1,5 @@
import time
import pyray as rl
from openpilot.common.params import Params
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.widgets import Widget
@@ -15,7 +14,7 @@ from openpilot.starpilot.common.experimental_state import (
class ExpButton(Widget):
def __init__(self, button_size: int, icon_size: int):
super().__init__()
self._params = Params()
self._params = ui_state.params
self._experimental_mode: bool = False
self._engageable: bool = False
+1 -2
View File
@@ -4,7 +4,6 @@ import pyray as rl
from cereal import messaging, car
from dataclasses import dataclass, field
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.common.params import Params
from openpilot.common.constants import CV
from openpilot.selfdrive.locationd.calibrationd import HEIGHT_INIT
from openpilot.selfdrive.ui.lib.starpilot_theme import get_param_color, get_theme_color, get_visual_color, is_stock_color_scheme, with_alpha
@@ -88,7 +87,7 @@ class ModelRenderer(Widget):
self._rainbow_path = RainbowPath()
# Get longitudinal control setting from car parameters
self._params = Params()
self._params = ui_state.params
if car_params := self._params.get("CarParams"):
cp = messaging.log_from_bytes(car_params, car.CarParams)
self._longitudinal_control = cp.openpilotLongitudinalControl
@@ -3,7 +3,6 @@ import time
import re
import json
from cereal import car
from openpilot.common.params import Params
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE
from openpilot.system.ui.lib.text_measure import measure_text_cached
@@ -64,7 +63,7 @@ def _setting_changed(value: float, reference: float) -> bool:
class DeveloperSidebar:
def __init__(self):
self._params = Params()
self._params = ui_state.params
self._font_bold = gui_app.font(FontWeight.SEMI_BOLD)
self._last_toggles_check = 0.0
self._cached_metrics = [0] * 7
@@ -1,7 +1,6 @@
import pyray as rl
import time
from msgq.visionipc import VisionStreamType
from openpilot.common.params import Params
from openpilot.selfdrive.ui.onroad.augmented_road_view import AugmentedRoadView
from openpilot.selfdrive.ui.onroad.starpilot.starpilot_border import render_behind, render_overlay, render_background_effects
from openpilot.selfdrive.ui.onroad.starpilot.path import render_adjacent_lanes, render_path_edges
@@ -31,7 +30,7 @@ AlertSize = log.SelfdriveState.AlertSize
class StarPilotOnroadView(AugmentedRoadView):
def __init__(self, stream_type: VisionStreamType = VisionStreamType.VISION_STREAM_ROAD):
super().__init__(stream_type)
self._params = Params()
self._params = ui_state.params
self._font_bold = gui_app.font(FontWeight.BOLD)
self._font_medium = gui_app.font(FontWeight.MEDIUM)
@@ -1,6 +1,5 @@
import pyray as rl
from typing import Optional
from openpilot.common.params import Params
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.selfdrive.ui.onroad.starpilot.widgets.base import LayoutWidget
from openpilot.selfdrive.ui.onroad.starpilot.slc_speed_limit import (
@@ -60,7 +59,7 @@ class SpeedLimitWidget(LayoutWidget):
)
if rl.check_collision_point_rec(mouse_pos, hit_rect):
current = ui_state.params.get_bool("SpeedLimitSources")
Params().put_bool("SpeedLimitSources", not current)
ui_state.params.put_bool("SpeedLimitSources", not current)
return
state = _get_slc_state()
+48 -1
View File
@@ -18,6 +18,53 @@ BACKLIGHT_OFFROAD = 65 if HARDWARE.get_device_type() == "mici" else 50
USBGPU_POLL_INTERVAL = 1.0
class CachedParams:
def __init__(self, ttl: float = 1.0):
self._params = Params()
self._cache = {}
self._wrappers = {}
self._ttl = ttl
def _invalidate(self, key=None):
if key is None:
self._cache.clear()
else:
k_str = key.decode("utf-8") if isinstance(key, bytes) else str(key)
self._cache = {k: v for k, v in self._cache.items() if k[0] != k_str}
def __getattr__(self, name: str):
if name in self._wrappers:
return self._wrappers[name]
attr = getattr(self._params, name)
if not callable(attr):
return attr
if name.startswith("get"):
def get_wrapper(key, *args, **kwargs):
now = time.monotonic()
k_str = key.decode("utf-8") if isinstance(key, bytes) else str(key)
ck = (k_str, name) if not args and not kwargs else (k_str, name, args, tuple(sorted(kwargs.items())))
val, expiry = self._cache.get(ck, (None, 0.0))
if now < expiry:
return val
val = attr(key, *args, **kwargs)
self._cache[ck] = (val, now + self._ttl)
return val
self._wrappers[name] = get_wrapper
return get_wrapper
if name.startswith("put") or name.startswith("remove") or name.startswith("clear"):
def put_wrapper(key=None, *args, **kwargs):
res = attr(key, *args, **kwargs) if key is not None else attr(*args, **kwargs)
self._invalidate(key)
return res
self._wrappers[name] = put_wrapper
return put_wrapper
return attr
class UIStatus(Enum):
DISENGAGED = "disengaged"
ENGAGED = "engaged"
@@ -34,7 +81,7 @@ class UIState:
return cls._instance
def _initialize(self):
self.params = Params()
self.params = CachedParams()
self.params_memory = Params(memory=True)
self.sm = messaging.SubMaster(
[