openpilot/dragonpilot/selfdrive/ui/layouts/settings/dragonpilot.py

306 lines
14 KiB
Python

import os
from openpilot.system.ui.widgets import Widget, DialogResult
from openpilot.common.params import Params, UnknownKeyName
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.widgets.scroller import Scroller
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.widgets.list_view import multiple_button_item, toggle_item, simple_item, button_item, spin_button_item, double_spin_button_item, text_spin_button_item
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dialog
class DragonpilotLayout(Widget):
def __init__(self):
super().__init__()
self._params = Params()
self._scroller: Scroller | None = None
self._has_long_ctrl = False
self._has_radar_unavailable = False
self._toggles = {}
if ui_state.CP is not None:
self._has_long_ctrl = ui_state.CP.openpilotLongitudinalControl
self._has_radar_unavailable = ui_state.CP.radarUnavailable
match ui_state.CP.brand:
case "toyota":
self._toyota_toggles()
case "volkswagen":
self._vag_toggles()
case "mazda":
self._mazda_toggles()
self._lat_toggles()
self._lon_toggles()
self._ui_toggles()
self._device_toggles()
self._reset_dp_conf_btn = button_item(
lambda: tr("Reset DP Settings"),
lambda: tr("RESET"),
lambda: tr("Reset dragonpilot settings to default and restart the device."),
callback=self._reset_dp_conf)
self._toggles['btn_reset_dp_conf'] = self._reset_dp_conf_btn
self._scroller = Scroller(list(self._toggles.values()), line_separator=True, spacing=0)
def _toyota_toggles(self):
self._toggles["title_toyota"] = simple_item(title=lambda: tr("### Toyota / Lexus ###"))
self._toggles["dp_toyota_door_auto_lock_unlock"] = toggle_item(
title=lambda: tr("Door Auto Lock/Unlock"),
description=lambda: tr("Enable openpilot to auto-lock doors above 20 km/h and auto-unlock when shifting to Park."),
initial_state=self._params.get_bool("dp_toyota_door_auto_lock_unlock"),
callback=lambda val: self._params.put_bool("dp_toyota_door_auto_lock_unlock", val),
)
self._toggles["dp_toyota_tss1_sng"] = toggle_item(
title=lambda: tr("Enable TSS1 SnG Mod"),
description=lambda: "",
initial_state=self._params.get_bool("dp_toyota_tss1_sng"),
callback=lambda val: self._params.put_bool("dp_toyota_tss1_sng", val),
)
self._toggles["dp_toyota_stock_lon"] = toggle_item(
title=lambda: tr("Use Stock Longitudinal Control"),
description=lambda: "",
initial_state=self._params.get_bool("dp_toyota_stock_lon"),
callback=lambda val: self._params.put_bool("dp_toyota_stock_lon", val),
)
def _vag_toggles(self):
self._toggles["title_vag"] = simple_item(title=lambda: tr("### VAG ###"))
self._toggles["dp_vag_a0_sng"] = toggle_item(
title=lambda: tr("MQB A0 SnG Mod"),
description=lambda: "",
initial_state=self._params.get_bool("dp_vag_a0_sng"),
callback=lambda val: self._params.put_bool("dp_vag_a0_sng", val),
)
self._toggles["dp_vag_pq_steering_patch"] = toggle_item(
title=lambda: tr("PQ Steering Patch"),
description=lambda: "",
initial_state=self._params.get_bool("dp_vag_pq_steering_patch"),
callback=lambda val: self._params.put_bool("dp_vag_pq_steering_patch", val),
)
self._toggles["dp_vag_avoid_eps_lockout"] = toggle_item(
title=lambda: tr("Avoid EPS Lockout"),
description=lambda: "",
initial_state=self._params.get_bool("dp_vag_avoid_eps_lockout"),
callback=lambda val: self._params.put_bool("dp_vag_avoid_eps_lockout", val),
)
def _mazda_toggles(self):
self._toggles["title_mazda"] = simple_item(title=lambda: tr("### Mazda ###"))
def _lat_toggles(self):
self._toggles["title_lat"] = simple_item(title=lambda: tr("### Lateral ###"))
self._toggles["dp_lat_alka"] = toggle_item(
title=lambda: tr("Always-on Lane Keeping Assist (ALKA)"),
description=lambda: tr("Allows openpilot to always steer to keep the car in its lane."),
initial_state=self._params.get_bool("dp_lat_alka"),
callback=lambda val: self._params.put_bool("dp_lat_alka", val),
)
self._toggles['dp_lat_lca_speed'] = spin_button_item(
title=lambda: tr('Lane Change Assist At:'),
description=lambda: tr("Off = Disable LCA.<br>1 mph = 1.2 km/h."),
initial_value=int(self._params.get("dp_lat_lca_speed") or 20),
callback=self._on_dp_lat_lca_speed_change,
min_val=0,
max_val=100,
step=5,
suffix=tr(" mph"),
special_value_text=tr("Off"),
)
self._toggles['dp_lat_lca_auto_sec'] = double_spin_button_item(
title=lambda: "+ " + tr('Auto Lane Change after:'),
description=lambda: tr("Off = Disable Auto Lane Change."),
initial_value=int(self._params.get("dp_lat_lca_auto_sec") or 0.0),
callback=lambda val: self._params.put("dp_lat_lca_auto_sec", float(val)),
min_val=0.0,
max_val=5.0,
step=0.5,
suffix=tr(" sec"),
special_value_text=tr("Off"),
# enabled=int(self._params.get("dp_lat_lca_speed") or 20) > 0
)
self._toggles['dp_lat_road_edge_detection'] = toggle_item(
title=lambda: tr('Road Edge Detection (RED)'),
description=lambda: tr("Block lane change assist when the system detects the road edge.<br>NOTE: This will show 'Car Detected in Blindspot' warning."),
initial_state=self._params.get_bool("dp_lat_road_edge_detection"),
callback=lambda val: self._params.put_bool("dp_lat_road_edge_detection", val),
)
def _lon_toggles(self):
self._toggles["title_lon"] = simple_item(title=lambda: tr("### Longitudinal ###"))
self._toggles['dp_lon_ext_radar'] = toggle_item(
title=lambda: tr("Use External Radar"),
description=lambda: tr("See https://github.com/eFiniLan/openpilot-ext-radar-addon for more information."),
initial_state=self._params.get_bool("dp_lon_ext_radar"),
callback=lambda val: self._params.put_bool("dp_lon_ext_radar", val),
)
self._toggles["dp_lon_acm"] = toggle_item(
title=lambda: tr("Enable Adaptive Coasting Mode (ACM)"),
description=tr("Adaptive Coasting Mode (ACM) reduces braking to allow smoother coasting when appropriate."),
initial_state=self._params.get_bool("dp_lon_acm"),
callback=lambda val: self._params.put_bool("dp_lon_acm", val),
)
self._toggles["dp_lon_aem"] = toggle_item(
title=lambda: tr("Adaptive Experimental Mode (AEM)"),
description=lambda: tr("Adaptive mode switcher between ACC and Blended based on driving context."),
initial_state=self._params.get_bool("dp_lon_aem"),
callback=lambda val: self._params.put_bool("dp_lon_aem", val),
)
self._toggles["dp_lon_dtsc"] = toggle_item(
title=lambda: tr("Dynamic Turn Speed Control (DTSC)"),
description=lambda: tr("DTSC automatically adjusts the vehicle's predicted speed based on upcoming road curvature and grip conditions.<br>Originally from the openpilot TACO branch."),
initial_state=self._params.get_bool("dp_lon_dtsc"),
callback=lambda val: self._params.put_bool("dp_lon_dtsc", val),
)
def _ui_toggles(self):
self._toggles["title_ui"] = simple_item(title=lambda: tr("### UI ###"))
self._toggles["dp_ui_hide_hud_speed_kph"] = spin_button_item(
title=lambda: tr("Hide HUD When Moves above:"),
description=lambda: tr("To prevent screen burn-in, hide Speed, MAX Speed, and Steering/DM Icons when the car moves.<br>Off = Stock Behavior<br>1 km/h = 0.6 mph"),
initial_value=int(self._params.get("dp_ui_hide_hud_speed_kph") or 0),
callback=lambda val: self._params.put("dp_ui_hide_hud_speed_kph", val),
suffix=tr(" km/h"),
min_val=0,
max_val=120,
step=5,
special_value_text=tr("Off"),
)
self._toggles["dp_ui_rainbow"] = toggle_item(
title=lambda: tr("Rainbow Driving Path like Tesla"),
description=lambda: tr("Why not?"),
initial_state=self._params.get_bool("dp_ui_rainbow"),
callback=lambda val: self._params.put_bool("dp_ui_rainbow", val),
)
self._toggles["dp_ui_lead"] = text_spin_button_item(
title=lambda: tr("Display Lead Stats"),
description=lambda: tr("Display the statistics of lead car and/or radar tracking points.<br>Lead: Lead stats only<br>Radar: Radar tracking point stats only<br>All: Lead and Radar stats<br>NOTE: Radar option only works on certain vehicle models."),
initial_index=int(self._params.get("dp_ui_lead") or 0),
callback=lambda val: self._params.put("dp_ui_lead", val),
options=["Off", "Lead", "Radar", "All"]
)
def _device_toggles(self):
self._toggles["title_dev"] = simple_item(title=lambda: tr("### Device ###"))
if "LITE" in os.environ:
self._toggles["dp_dev_is_rhd"] = toggle_item(
title=lambda: tr("Enable Right-Hand Drive Mode"),
description=lambda: tr("Allow openpilot to obey right-hand traffic conventions on right driver seat."),
initial_state=self._params.get_bool("dp_dev_is_rhd"),
callback=lambda val: self._params.put_bool("dp_dev_is_rhd", val),
)
self._toggles["dp_dev_monitoring_disabled"] = toggle_item(
title=lambda: tr("Disable Driver Monitoring"),
description=lambda: tr("USE AT YOUR OWN RISK."),
initial_state=self._params.get_bool("dp_dev_monitoring_disabled"),
callback=lambda val: self._params.put_bool("dp_dev_monitoring_disabled", val),
)
self._toggles["dp_dev_beep"] = toggle_item(
title=lambda: tr("Enable Beep (Warning)"),
description=lambda: tr("Use Buzzer for audiable alerts."),
initial_state=self._params.get_bool("dp_dev_beep"),
callback=lambda val: self._params.put_bool("dp_dev_beep", val),
)
self._toggles["dp_ui_display_mode"] = text_spin_button_item(
title=lambda: tr("Display Mode"),
callback=lambda val: self._params.put("dp_ui_display_mode", val),
options=["Std.", "MAIN+", "OP+", "MAIN-", "OP-"],
initial_index=int(self._params.get("dp_ui_display_mode") or 0),
description=lambda: tr("Std.: Stock behavior.<br>MAIN+: ACC MAIN on = Display ON.<br>OP+: OP enabled = Display ON.<br>MAIN-: ACC MAIN on = Display OFF<br>OP-: OP enabled = Display OFF."),
)
if "LITE" not in os.environ:
self._toggles["dp_dev_audible_alert_mode"] = text_spin_button_item(
title=lambda: tr("Audible Alert"),
description=lambda: tr("Std.: Stock behaviour.<br>Warning: Only emits sound when there is a warning.<br>Off: Does not emit any sound at all."),
initial_index=int(self._params.get("dp_dev_audible_alert_mode") or 0),
callback=lambda val: self._params.put("dp_dev_audible_alert_mode", val),
options=["Std.", "Warning", "Off"],
)
self._toggles["dp_dev_auto_shutdown_in"] = spin_button_item(
title=lambda: tr("Auto Shutdown After"),
description=lambda: tr("0 mins = Immediately"),
initial_value=int(self._params.get("dp_dev_auto_shutdown_in") or -5),
callback=lambda val: self._params.put("dp_dev_auto_shutdown_in", val),
min_val=-5,
max_val=300,
step=5,
suffix=tr(" mins"),
special_value_text=tr("Off"),
)
self._toggles["dp_dev_dashy"] = text_spin_button_item(
title=lambda: tr("dashy"),
description=lambda: tr("dashy - dragonpilot's all-in-one system hub for you.<br><br>Visit http://<device_ip>:5088 to access.<br><br>Off - Turn off dashy completely.<br>File: File Manager only.<br>All: File Manager + Live Stream."),
initial_index=int(self._params.get("dp_dev_dashy") or 0),
callback=lambda val: self._params.put("dp_dev_dashy", val),
options=[tr("Off"), tr("File"), tr("All")],
)
self._toggles["dp_dev_delay_loggerd"] = spin_button_item(
title=lambda: tr("Delay Starting Loggerd for:"),
description=lambda: tr("Delays the startup of loggerd and its related processes when the device goes on-road.<br>This prevents the initial moments of a drive from being recorded, protecting location privacy at the start of a trip."),
initial_value=int(self._params.get("dp_dev_delay_loggerd") or 0),
callback=lambda val: self._params.put("dp_dev_delay_loggerd", val),
min_val=0,
max_val=300,
step=5,
suffix=tr(" secs"),
special_value_text=tr("Off"),
)
self._toggles["dp_dev_disable_connect"] = toggle_item(
title=lambda: tr("Disable Comma Connect"),
description=lambda: tr("Disable Comma connect service if you do not wish to upload / being tracked by the service."),
initial_state=self._params.get_bool("dp_dev_disable_connect"),
callback=lambda val: self._params.put_bool("dp_dev_disable_connect", val),
)
def _reset_dp_conf(self):
def reset_dp_conf(result: int):
# Check engaged again in case it changed while the dialog was open
if result != DialogResult.CONFIRM:
return
self._params.put_bool_nonblocking("dp_dev_reset_conf", True)
dialog = ConfirmDialog(tr("Are you sure you want to reset ALL DP SETTINGS to default?"), tr("Reset"))
gui_app.set_modal_overlay(dialog, callback=reset_dp_conf)
def show_event(self):
self._scroller.show_event()
self._update_toggles()
def _update_toggles(self):
ui_state.update_params()
def _render(self, rect):
self._scroller.render(rect)
def _on_dp_lat_lca_speed_change(self, val):
self._params.put("dp_lat_lca_speed", int(val))
self._toggles['dp_lat_lca_auto_sec'].action_item.set_enabled(val > 0)