mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-07-10 01:02:11 +08:00
Compare commits
91 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| acb4bb848b | |||
| 0cd913d7ac | |||
| 7fd1fea3b0 | |||
| e79c3243b2 | |||
| a936c311d7 | |||
| 8e53fe176d | |||
| 22a12aec35 | |||
| 426c2abd61 | |||
| 1a84559cec | |||
| 65b61fd965 | |||
| a01449822f | |||
| f52db76444 | |||
| b61f095ef2 | |||
| 59e5fd7fe6 | |||
| 607811b6ad | |||
| 2414fe287d | |||
| f7a4dbc47f | |||
| fd0a5f806c | |||
| de62240e97 | |||
| adba29da1b | |||
| 6d6a91c318 | |||
| 7259687578 | |||
| 83a07e4bfa | |||
| cb65777186 | |||
| 282b867fcb | |||
| 3fd3c31966 | |||
| f3c3581472 | |||
| 465daf323c | |||
| 3fe8e155b6 | |||
| c0bffa2a8c | |||
| c9edcaa1a6 | |||
| 76101207cb | |||
| 62b01d3799 | |||
| a3be1edde7 | |||
| 7869542683 | |||
| 981aab0500 | |||
| 9c82592906 | |||
| 5d3f95d420 | |||
| f8d19fe9dd | |||
| 9d711350c2 | |||
| 45c853c87a | |||
| e8ab9d812d | |||
| ed775185f2 | |||
| 7bbbc6588e | |||
| e68c65d15d | |||
| 0db8722221 | |||
| a33497ed19 | |||
| 91f2bf3459 | |||
| 7fad2fc189 | |||
| e74252bdf5 | |||
| 6b795ab513 | |||
| 3b1b4ef90f | |||
| 48d33e98e7 | |||
| 2717d97350 | |||
| 64232397ed | |||
| 0613442ac9 | |||
| 93ab6ee06b | |||
| 4baa170cfa | |||
| 2be95225b1 | |||
| f8e8c59dd5 | |||
| dd9d4bedf4 | |||
| ada449989b | |||
| 68c7f69439 | |||
| 1db71aff57 | |||
| 942ccb90dd | |||
| e6f5aae246 | |||
| 7032e4a972 | |||
| ffa78eabaa | |||
| 5b03369a8f | |||
| 1e0564b484 | |||
| eb94abaa14 | |||
| 4da32cc009 | |||
| 4820265268 | |||
| 01aa6c4204 | |||
| 21beea51ec | |||
| 98c479830c | |||
| 5369b6880f | |||
| a9e57f0a76 | |||
| 712a358c94 | |||
| 423a7d2ed0 | |||
| e4e10d4b87 | |||
| 632e9d13b2 | |||
| 362e9ce04b | |||
| 51d0666c85 | |||
| deda1329a2 | |||
| 4110749cb0 | |||
| 3946e643f6 | |||
| 0c37a38596 | |||
| 9c5acf61c0 | |||
| 121b304fe0 | |||
| 47d848293b |
@@ -179,6 +179,8 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"RocketFuel", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"RocketFuel", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ScreenSaverEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ScreenSaverTimeout", {PERSISTENT | BACKUP, INT, "300"}},
|
||||||
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from openpilot.system.ui.sunnypilot.widgets.option_control import OptionControlS
|
|||||||
from openpilot.system.ui.widgets import Widget
|
from openpilot.system.ui.widgets import Widget
|
||||||
from openpilot.system.ui.lib.multilang import tr
|
from openpilot.system.ui.lib.multilang import tr
|
||||||
from openpilot.system.ui.widgets.scroller_tici import Scroller
|
from openpilot.system.ui.widgets.scroller_tici import Scroller
|
||||||
from openpilot.system.ui.sunnypilot.widgets.list_view import option_item_sp, ToggleActionSP
|
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp, option_item_sp, ToggleActionSP
|
||||||
from openpilot.sunnypilot.system.params_migration import ONROAD_BRIGHTNESS_TIMER_VALUES
|
from openpilot.sunnypilot.system.params_migration import ONROAD_BRIGHTNESS_TIMER_VALUES
|
||||||
|
|
||||||
|
|
||||||
@@ -64,10 +64,27 @@ class DisplayLayout(Widget):
|
|||||||
f"{value} s" if value < 60 else f"{int(value/60)} m"),
|
f"{value} s" if value < 60 else f"{int(value/60)} m"),
|
||||||
inline=True
|
inline=True
|
||||||
)
|
)
|
||||||
|
self._screensaver_toggle = toggle_item_sp(
|
||||||
|
param="ScreenSaverEnabled",
|
||||||
|
title=lambda: tr("Enable sunnypilot Screen Saver"),
|
||||||
|
description=lambda: tr("Enable screen saver when the device is offroad & idle. " +
|
||||||
|
"The screen saver will kick off after the interactivity timeout expires, and will stay on for the duration configured below."),
|
||||||
|
)
|
||||||
|
self._screensaver_timeout = option_item_sp(
|
||||||
|
param="ScreenSaverTimeout",
|
||||||
|
title=lambda: tr("Screen Saver Timeout"),
|
||||||
|
description=lambda: tr("Configure how long the screen saver should stay on after the interactivity timeout expires."),
|
||||||
|
min_value=60,
|
||||||
|
max_value=600,
|
||||||
|
value_change_step=60,
|
||||||
|
label_callback=lambda value: f"{int(value/60)} m"
|
||||||
|
)
|
||||||
items = [
|
items = [
|
||||||
self._onroad_brightness,
|
self._onroad_brightness,
|
||||||
self._onroad_brightness_timer,
|
self._onroad_brightness_timer,
|
||||||
self._interactivity_timeout,
|
self._interactivity_timeout,
|
||||||
|
self._screensaver_toggle,
|
||||||
|
self._screensaver_timeout,
|
||||||
]
|
]
|
||||||
return items
|
return items
|
||||||
|
|
||||||
@@ -100,6 +117,8 @@ class DisplayLayout(Widget):
|
|||||||
brightness_val = self._params.get("OnroadScreenOffBrightness", return_default=True)
|
brightness_val = self._params.get("OnroadScreenOffBrightness", return_default=True)
|
||||||
self._onroad_brightness_timer.action_item.set_enabled(brightness_val not in (OnroadBrightness.AUTO, OnroadBrightness.AUTO_DARK))
|
self._onroad_brightness_timer.action_item.set_enabled(brightness_val not in (OnroadBrightness.AUTO, OnroadBrightness.AUTO_DARK))
|
||||||
|
|
||||||
|
self._screensaver_timeout.set_visible(self._screensaver_toggle.action_item.get_state())
|
||||||
|
|
||||||
def _render(self, rect):
|
def _render(self, rect):
|
||||||
self._scroller.render(rect)
|
self._scroller.render(rect)
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from openpilot.common.params import Params
|
|||||||
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.display import OnroadBrightness
|
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.display import OnroadBrightness
|
||||||
from openpilot.sunnypilot.sunnylink.sunnylink_state import SunnylinkState
|
from openpilot.sunnypilot.sunnylink.sunnylink_state import SunnylinkState
|
||||||
from openpilot.system.ui.lib.application import gui_app
|
from openpilot.system.ui.lib.application import gui_app
|
||||||
|
from openpilot.system.ui.sunnypilot.widgets.screen_saver import ScreenSaverSP
|
||||||
|
|
||||||
OpenpilotState = log.SelfdriveState.OpenpilotState
|
OpenpilotState = log.SelfdriveState.OpenpilotState
|
||||||
MADSState = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState
|
MADSState = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState
|
||||||
@@ -34,6 +35,8 @@ class UIStateSP:
|
|||||||
]
|
]
|
||||||
|
|
||||||
self.sunnylink_state = SunnylinkState()
|
self.sunnylink_state = SunnylinkState()
|
||||||
|
self.screensaver = ScreenSaverSP()
|
||||||
|
|
||||||
self.update_params()
|
self.update_params()
|
||||||
|
|
||||||
self.onroad_brightness_timer: int = 0
|
self.onroad_brightness_timer: int = 0
|
||||||
@@ -146,14 +149,27 @@ class UIStateSP:
|
|||||||
self.true_v_ego_ui = self.params.get_bool("TrueVEgoUI")
|
self.true_v_ego_ui = self.params.get_bool("TrueVEgoUI")
|
||||||
self.turn_signals = self.params.get_bool("ShowTurnSignals")
|
self.turn_signals = self.params.get_bool("ShowTurnSignals")
|
||||||
self.boot_offroad_mode = self.params.get("DeviceBootMode", return_default=True)
|
self.boot_offroad_mode = self.params.get("DeviceBootMode", return_default=True)
|
||||||
|
self.screensaver_enabled = self.params.get_bool("ScreenSaverEnabled")
|
||||||
|
|
||||||
|
|
||||||
class DeviceSP:
|
class DeviceSP:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _set_awake(on: bool, _ui_state):
|
def _set_awake(_device, on: bool, _ui_state):
|
||||||
if _ui_state.boot_offroad_mode == 1 and not on:
|
if _ui_state.boot_offroad_mode == 1 and not on:
|
||||||
_ui_state.params.put_bool("OffroadMode", True)
|
_ui_state.params.put_bool("OffroadMode", True)
|
||||||
|
|
||||||
|
if not on and _ui_state.screensaver_enabled:
|
||||||
|
if _ui_state.screensaver.was_dismissed:
|
||||||
|
_ui_state.screensaver.deinit()
|
||||||
|
gui_app.pop_widget()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
_ui_state.screensaver.initialize(dismiss_callback=lambda: _device._set_awake(False))
|
||||||
|
gui_app.push_widget(_ui_state.screensaver)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_onroad_brightness(_ui_state, awake: bool, cur_brightness: float) -> float:
|
def set_onroad_brightness(_ui_state, awake: bool, cur_brightness: float) -> float:
|
||||||
if not awake or not _ui_state.started:
|
if not awake or not _ui_state.started:
|
||||||
|
|||||||
@@ -299,11 +299,11 @@ class Device(DeviceSP):
|
|||||||
|
|
||||||
def _set_awake(self, on: bool):
|
def _set_awake(self, on: bool):
|
||||||
if on != self._awake:
|
if on != self._awake:
|
||||||
DeviceSP._set_awake(on, ui_state)
|
if DeviceSP._set_awake(self, on, ui_state):
|
||||||
self._awake = on
|
self._awake = on
|
||||||
cloudlog.debug(f"setting display power {int(on)}")
|
cloudlog.debug(f"setting display power {int(on)}")
|
||||||
HARDWARE.set_display_power(on)
|
HARDWARE.set_display_power(on)
|
||||||
gui_app.set_should_render(on)
|
gui_app.set_should_render(on)
|
||||||
|
|
||||||
|
|
||||||
# Global instance
|
# Global instance
|
||||||
|
|||||||
@@ -1126,6 +1126,14 @@
|
|||||||
"title": "Route Count",
|
"title": "Route Count",
|
||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
|
"ScreenSaverEnabled": {
|
||||||
|
"title": "Enable Screen Saver",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"ScreenSaverTimeout": {
|
||||||
|
"title": "Screen Saver Timeout",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
"SecOCKey": {
|
"SecOCKey": {
|
||||||
"title": "Sec Oc Key",
|
"title": "Sec Oc Key",
|
||||||
"description": ""
|
"description": ""
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
|
import pyray as rl
|
||||||
|
|
||||||
|
from openpilot.common.params import Params
|
||||||
|
from openpilot.system.hardware import HARDWARE
|
||||||
|
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||||
|
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||||
|
from openpilot.system.ui.widgets import Widget
|
||||||
|
|
||||||
|
class ScreenSaverSP(Widget):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.set_rect(rl.Rectangle(0, 0, gui_app.width, gui_app.height))
|
||||||
|
self.screensaver_timeout = Params().get("ScreenSaverTimeout", return_default=True)
|
||||||
|
self._is_mici = HARDWARE.get_device_type() == 'mici' or (HARDWARE.get_device_type() == "pc" and os.getenv("BIG") != "1")
|
||||||
|
|
||||||
|
self.x = 0.0
|
||||||
|
self.y = 100.0
|
||||||
|
self.vx = 120.0 if self._is_mici else 300.0
|
||||||
|
self.vy = 70.0 if self._is_mici else 200.0
|
||||||
|
self._hue = 150
|
||||||
|
self.color = rl.color_from_hsv(self._hue, 1, 1)
|
||||||
|
|
||||||
|
self.text = "sunnypilot"
|
||||||
|
self.font_size = 50 if self._is_mici else 200
|
||||||
|
self._start_time = None
|
||||||
|
self._dismiss = False
|
||||||
|
self.dismiss_callback = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def was_dismissed(self) -> bool:
|
||||||
|
return self._dismiss
|
||||||
|
|
||||||
|
def initialize(self, dismiss_callback: Callable):
|
||||||
|
if self._start_time is None:
|
||||||
|
self._start_time = time.monotonic()
|
||||||
|
self.dismiss_callback = dismiss_callback
|
||||||
|
self._dismiss = False
|
||||||
|
|
||||||
|
def deinit(self):
|
||||||
|
self._dismiss = False
|
||||||
|
self._start_time = None
|
||||||
|
|
||||||
|
def _handle_mouse_press(self, mouse_pos):
|
||||||
|
self._reset()
|
||||||
|
return super()._handle_mouse_press(mouse_pos)
|
||||||
|
|
||||||
|
def _reset(self):
|
||||||
|
self._dismiss = True
|
||||||
|
self._start_time = None
|
||||||
|
|
||||||
|
def _update_state(self):
|
||||||
|
super()._update_state()
|
||||||
|
|
||||||
|
self.font = gui_app.font(FontWeight.AUDIOWIDE)
|
||||||
|
text_size = measure_text_cached(self.font, self.text, self.font_size, 0)
|
||||||
|
self.logo_width = text_size.x
|
||||||
|
self.logo_height = text_size.y
|
||||||
|
|
||||||
|
if self._start_time and time.monotonic() - self._start_time > self.screensaver_timeout:
|
||||||
|
self._reset()
|
||||||
|
|
||||||
|
dt = rl.get_frame_time()
|
||||||
|
|
||||||
|
self.x += self.vx * dt
|
||||||
|
self.y += self.vy * dt
|
||||||
|
|
||||||
|
hit_x = hit_y = False
|
||||||
|
if self.x + self.logo_width > self.rect.width:
|
||||||
|
self.vx *= -1
|
||||||
|
self.x = self.rect.width - self.logo_width
|
||||||
|
hit_x = True
|
||||||
|
elif self.x < 0:
|
||||||
|
self.vx *= -1
|
||||||
|
self.x = 0
|
||||||
|
hit_x = True
|
||||||
|
|
||||||
|
if self.y + self.logo_height > self.rect.height:
|
||||||
|
self.vy *= -1
|
||||||
|
self.y = self.rect.height - self.logo_height
|
||||||
|
hit_y = True
|
||||||
|
elif self.y < 0:
|
||||||
|
self.vy *= -1
|
||||||
|
self.y = 0
|
||||||
|
hit_y = True
|
||||||
|
|
||||||
|
def hue_dist(a, b):
|
||||||
|
d = abs(a - b)
|
||||||
|
return min(d, 360 - d)
|
||||||
|
|
||||||
|
if hit_x or hit_y:
|
||||||
|
while hue_dist((new_hue := rl.get_random_value(0, 360)), self._hue) < 90:
|
||||||
|
pass
|
||||||
|
self._hue = new_hue
|
||||||
|
self.color = rl.color_from_hsv(self._hue, 1, 1)
|
||||||
|
|
||||||
|
def _render(self, rect: rl.Rectangle):
|
||||||
|
if self._dismiss:
|
||||||
|
self.dismiss_callback()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
self.set_rect(rect)
|
||||||
|
rl.clear_background(rl.BLACK)
|
||||||
|
rl.draw_text_ex(self.font, self.text, rl.Vector2(int(self.x), int(self.y)), self.font_size, 0, self.color)
|
||||||
|
return -1
|
||||||
Reference in New Issue
Block a user