mirror of
https://github.com/infiniteCable2/openpilot.git
synced 2026-10-12 17:33:41 +08:00
battery panel
This commit is contained in:
@@ -60,8 +60,8 @@ class SettingsLayout(Widget):
|
||||
self._panels = {
|
||||
PanelType.DEVICE: PanelInfo(tr_noop("Device"), DeviceLayout()),
|
||||
PanelType.NETWORK: PanelInfo(tr_noop("Network"), NetworkUI(wifi_manager)),
|
||||
PanelType.ICTOGGLES: PanelInfo(tr_noop("infiniteCableCustom"), ICTogglesLayout()),
|
||||
PanelType.TOGGLES: PanelInfo(tr_noop("Toggles"), TogglesLayout()),
|
||||
PanelType.ICTOGGLES: PanelInfo(tr_noop("infiniteCable"), ICTogglesLayout()),
|
||||
PanelType.SOFTWARE: PanelInfo(tr_noop("Software"), SoftwareLayout()),
|
||||
PanelType.FIREHOSE: PanelInfo(tr_noop("Firehose"), FirehoseLayout()),
|
||||
PanelType.DEVELOPER: PanelInfo(tr_noop("Developer"), DeveloperLayout()),
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import pyray as rl
|
||||
from dataclasses import dataclass
|
||||
|
||||
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
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BatteryPanelConfig:
|
||||
scale_factor: float = 1.1
|
||||
panel_width_ratio: float = 0.7 # 70 % der Breite von rechts
|
||||
panel_margin: int = 30 # Abstand zum Rand
|
||||
line_height: int = 48 # Basis-Zeilenhöhe
|
||||
label_width: int = 265
|
||||
text_margin: int = 25 # Abstand Label → Wert
|
||||
|
||||
CONFIG = BatteryPanelConfig()
|
||||
|
||||
class BatteryDetails(Widget):
|
||||
def __init__(self, button_size: int, icon_size: int):
|
||||
super().__init__()
|
||||
self._params = Params()
|
||||
|
||||
self._capacity: float = 0.0
|
||||
self._charge: float = 0.0
|
||||
self._soc: float = 0.0
|
||||
self._temperature: float = 0.0
|
||||
self._heaterActive: bool = False
|
||||
self._voltage: float = 0.0
|
||||
self._current: float = 0.0
|
||||
self._power: float = 0.0
|
||||
|
||||
self._font: rl.Font = gui_app.font(FontWeight.MEDIUM)
|
||||
self._panel_bg: rl.Color = rl.Color(0, 0, 0, 128)
|
||||
self._text_color: rl.Color = rl.Color(255, 255, 255, 255)
|
||||
|
||||
self._display_enabled: bool = False
|
||||
|
||||
def _update_state(self) -> None:
|
||||
self._display_enabled = self._params.get_bool("BatteryDetails")
|
||||
if not self._display_enabled:
|
||||
return
|
||||
|
||||
sm = ui_state.sm
|
||||
if sm.recv_frame["carState"] < ui_state.started_frame:
|
||||
self._reset_values()
|
||||
return
|
||||
|
||||
car_state = sm["carState"]
|
||||
|
||||
battery_data = car_state.batteryDetails
|
||||
self._capacity = float(battery_data.capacity)
|
||||
self._charge = float(battery_data.charge)
|
||||
self._soc = float(battery_data.soc)
|
||||
self._temperature = float(battery_data.temperature)
|
||||
self._heater_active = bool(battery_data.heaterActive)
|
||||
self._voltage = float(battery_data.voltage)
|
||||
self._current = float(battery_data.current)
|
||||
self._power = float(battery_data.power)
|
||||
|
||||
def _reset_values(self) -> None:
|
||||
self._capacity = 0.0
|
||||
self._charge = 0.0
|
||||
self._soc = 0.0
|
||||
self._temperature = 0.0
|
||||
self._heater_active = False
|
||||
self._voltage = 0.0
|
||||
self._current = 0.0
|
||||
self._power = 0.0
|
||||
|
||||
def _render(self, rect: rl.Rectangle) -> None:
|
||||
if not self._display_enabled:
|
||||
return
|
||||
|
||||
scale = CONFIG.scale_factor
|
||||
base_line_h = CONFIG.line_height
|
||||
line_h = int(base_line_h * scale)
|
||||
|
||||
panel_width = int(rect.width * CONFIG.panel_width_ratio)
|
||||
panel_height = line_h * 4
|
||||
|
||||
panel_margin = CONFIG.panel_margin
|
||||
|
||||
x_start = int(rect.x + rect.width - panel_width - panel_margin)
|
||||
y_start = int(rect.y + rect.height - panel_margin - panel_height)
|
||||
|
||||
panel_rect = rl.Rectangle(x_start, y_start, panel_width, panel_height)
|
||||
rl.draw_rectangle_rounded(panel_rect, 0.1, 8, self._panel_bg)
|
||||
|
||||
label_width = CONFIG.label_width
|
||||
text_margin = CONFIG.text_margin
|
||||
column_spacing = panel_width // 2 - 20
|
||||
value_width = column_spacing - label_width - text_margin
|
||||
|
||||
labels = [
|
||||
"Capacity:", "Charge:", "SoC:", "Temperature:",
|
||||
"Heater Active:", "Voltage:", "Current:", "Power:",
|
||||
]
|
||||
|
||||
values = [
|
||||
f"{self._capacity:.2f} Wh",
|
||||
f"{self._charge:.2f} Wh",
|
||||
f"{self._soc:.2f} %",
|
||||
f"{self._temperature:.2f} °C",
|
||||
"True" if self._heater_active else "False",
|
||||
f"{self._voltage:.2f} V",
|
||||
f"{self._current:.2f} A",
|
||||
f"{self._power:.2f} kW",
|
||||
]
|
||||
|
||||
rl.draw_text_ex
|
||||
|
||||
for i, (label, value) in enumerate(zip(labels, values)):
|
||||
column = i // 4
|
||||
row = i % 4
|
||||
|
||||
base_x = x_start + column * column_spacing
|
||||
base_y = y_start + row * line_h
|
||||
|
||||
label_pos = rl.Vector2(float(base_x), float(base_y))
|
||||
rl.draw_text_ex(
|
||||
self._font,
|
||||
label,
|
||||
label_pos,
|
||||
40 * scale,
|
||||
0,
|
||||
self._text_color,
|
||||
)
|
||||
|
||||
value_x = base_x + label_width + text_margin
|
||||
value_pos = rl.Vector2(float(value_x), float(base_y))
|
||||
rl.draw_text_ex(
|
||||
self._font,
|
||||
value,
|
||||
value_pos,
|
||||
40 * scale,
|
||||
0,
|
||||
self._text_color,
|
||||
)
|
||||
@@ -2,6 +2,7 @@ import pyray as rl
|
||||
from dataclasses import dataclass
|
||||
from openpilot.common.constants import CV
|
||||
from openpilot.selfdrive.ui.onroad.exp_button import ExpButton
|
||||
from openpilot.selfdrive.ui.onroad.battery_details import BatteryDetails
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
@@ -71,6 +72,7 @@ class HudRenderer(Widget):
|
||||
self._font_medium: rl.Font = gui_app.font(FontWeight.MEDIUM)
|
||||
|
||||
self._exp_button: ExpButton = ExpButton(UI_CONFIG.button_size, UI_CONFIG.wheel_icon_size)
|
||||
self._battery_details = BatteryDetails()
|
||||
|
||||
def _update_state(self) -> None:
|
||||
"""Update HUD state based on car state and controls state."""
|
||||
@@ -99,6 +101,8 @@ class HudRenderer(Widget):
|
||||
v_ego = v_ego_cluster if self.v_ego_cluster_seen else car_state.vEgo
|
||||
speed_conversion = CV.MS_TO_KPH if ui_state.is_metric else CV.MS_TO_MPH
|
||||
self.speed = max(0.0, v_ego * speed_conversion)
|
||||
|
||||
self._battery_details.update()
|
||||
|
||||
def _render(self, rect: rl.Rectangle) -> None:
|
||||
"""Render HUD elements to the screen."""
|
||||
@@ -119,6 +123,7 @@ class HudRenderer(Widget):
|
||||
|
||||
button_x = rect.x + rect.width - UI_CONFIG.border_size - UI_CONFIG.button_size
|
||||
button_y = rect.y + UI_CONFIG.border_size
|
||||
self._battery_details.render(rect)
|
||||
self._exp_button.render(rl.Rectangle(button_x, button_y, UI_CONFIG.button_size, UI_CONFIG.button_size))
|
||||
|
||||
def user_interacting(self) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user