mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-10 18:23:44 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95a7f3b398 |
@@ -99,6 +99,7 @@ def _should_publish_model_output(model_output, vipc_dropped_frames: int, externa
|
|||||||
MIN_LAT_CONTROL_SPEED = 0.3
|
MIN_LAT_CONTROL_SPEED = 0.3
|
||||||
BIG_MODEL_LOAD_WAIT_TIMEOUT_MS = 30000
|
BIG_MODEL_LOAD_WAIT_TIMEOUT_MS = 30000
|
||||||
BIG_MODEL_RUN_WAIT_TIMEOUT_MS = 3000
|
BIG_MODEL_RUN_WAIT_TIMEOUT_MS = 3000
|
||||||
|
EXTERNAL_GPU_TEST_POWER_LIMIT_W = 60
|
||||||
EXTERNAL_GPU_POWER_READY_MV = 10000
|
EXTERNAL_GPU_POWER_READY_MV = 10000
|
||||||
EXTERNAL_GPU_EGMP_READY_MV = 12500
|
EXTERNAL_GPU_EGMP_READY_MV = 12500
|
||||||
EXTERNAL_GPU_POWER_STABLE_SECONDS = 3.0
|
EXTERNAL_GPU_POWER_STABLE_SECONDS = 3.0
|
||||||
@@ -115,6 +116,12 @@ def _set_hcq_wait_timeout(timeout_ms: int) -> None:
|
|||||||
getenv.cache_clear()
|
getenv.cache_clear()
|
||||||
|
|
||||||
|
|
||||||
|
def _set_external_gpu_power_limit(watts: int) -> None:
|
||||||
|
os.environ["AM_POWER_LIMIT"] = str(watts)
|
||||||
|
from tinygrad.helpers import getenv
|
||||||
|
getenv.cache_clear()
|
||||||
|
|
||||||
|
|
||||||
def _external_gpu_power_voltage(device_type: str, panda_states, peripheral_state) -> int | None:
|
def _external_gpu_power_voltage(device_type: str, panda_states, peripheral_state) -> int | None:
|
||||||
if device_type == "tici":
|
if device_type == "tici":
|
||||||
voltage = int(peripheral_state.voltage)
|
voltage = int(peripheral_state.voltage)
|
||||||
@@ -1053,6 +1060,9 @@ def main(demo=False):
|
|||||||
external_artifact = MODELS_PATH / f"{big_model_id}_driving_tinygrad.pkl"
|
external_artifact = MODELS_PATH / f"{big_model_id}_driving_tinygrad.pkl"
|
||||||
external_artifact_ready = external_model_selected and file_chunked_exists(external_artifact)
|
external_artifact_ready = external_model_selected and file_chunked_exists(external_artifact)
|
||||||
external_gpu_requested = usbgpu_present_now and (bool(big_model_id) or model_lab_ready)
|
external_gpu_requested = usbgpu_present_now and (bool(big_model_id) or model_lab_ready)
|
||||||
|
if external_gpu_requested:
|
||||||
|
_set_external_gpu_power_limit(EXTERNAL_GPU_TEST_POWER_LIMIT_W)
|
||||||
|
cloudlog.warning(f"external GPU test power limit set to {EXTERNAL_GPU_TEST_POWER_LIMIT_W} W")
|
||||||
params.put_bool("UsbGpuPresent", usbgpu_present_now)
|
params.put_bool("UsbGpuPresent", usbgpu_present_now)
|
||||||
params.put_bool("UsbGpuCompiled", external_artifact_ready or model_lab_ready)
|
params.put_bool("UsbGpuCompiled", external_artifact_ready or model_lab_ready)
|
||||||
params.put_bool("UsbGpuActive", False)
|
params.put_bool("UsbGpuActive", False)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import io
|
import io
|
||||||
|
import os
|
||||||
import struct
|
import struct
|
||||||
from types import MethodType
|
from types import MethodType
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
@@ -39,6 +40,17 @@ def test_external_gpu_uses_a_longer_load_watchdog():
|
|||||||
assert modeld.BIG_MODEL_RUN_WAIT_TIMEOUT_MS == 3000
|
assert modeld.BIG_MODEL_RUN_WAIT_TIMEOUT_MS == 3000
|
||||||
|
|
||||||
|
|
||||||
|
def test_external_gpu_test_power_limit(monkeypatch):
|
||||||
|
from tinygrad.helpers import getenv
|
||||||
|
|
||||||
|
monkeypatch.delenv("AM_POWER_LIMIT", raising=False)
|
||||||
|
getenv.cache_clear()
|
||||||
|
modeld._set_external_gpu_power_limit(modeld.EXTERNAL_GPU_TEST_POWER_LIMIT_W)
|
||||||
|
|
||||||
|
assert os.environ["AM_POWER_LIMIT"] == "60"
|
||||||
|
assert getenv("AM_POWER_LIMIT", 0.0) == 60.0
|
||||||
|
|
||||||
|
|
||||||
def test_external_gpu_voltage_uses_hardware_specific_source():
|
def test_external_gpu_voltage_uses_hardware_specific_source():
|
||||||
panda_type = modeld.log.PandaState.PandaType
|
panda_type = modeld.log.PandaState.PandaType
|
||||||
panda_states = [SimpleNamespace(pandaType=panda_type.dos, voltage=230)]
|
panda_states = [SimpleNamespace(pandaType=panda_type.dos, voltage=230)]
|
||||||
|
|||||||
@@ -780,12 +780,7 @@ class StarPilotLongitudinalLayout(_SettingsPage):
|
|||||||
SettingRow("PulseGlideSpeedDelta", "value", tr_noop("Pulse and Glide Delta"),
|
SettingRow("PulseGlideSpeedDelta", "value", tr_noop("Pulse and Glide Delta"),
|
||||||
subtitle=tr_noop("Developer-only: coast this far below the current cruise target before accelerating back up."),
|
subtitle=tr_noop("Developer-only: coast this far below the current cruise target before accelerating back up."),
|
||||||
get_value=lambda: f"{self._params.get_float('PulseGlideSpeedDelta'):.1f}{self._speed_unit()}",
|
get_value=lambda: f"{self._params.get_float('PulseGlideSpeedDelta'):.1f}{self._speed_unit()}",
|
||||||
on_click=lambda: self._show_slider("PulseGlideSpeedDelta", 0.5,
|
on_click=lambda: self._show_slider("PulseGlideSpeedDelta"),
|
||||||
30.0 if self._is_metric() else 15.0,
|
|
||||||
step=0.5,
|
|
||||||
unit=self._speed_unit(),
|
|
||||||
value_type="float",
|
|
||||||
title="Pulse and Glide Delta"),
|
|
||||||
visible=lambda: self._params.get_bool("QOLLongitudinal") and self._developer_feature_access()),
|
visible=lambda: self._params.get_bool("QOLLongitudinal") and self._developer_feature_access()),
|
||||||
SettingRow("MapGears", "toggle", tr_noop("Map Gears"),
|
SettingRow("MapGears", "toggle", tr_noop("Map Gears"),
|
||||||
subtitle="",
|
subtitle="",
|
||||||
@@ -1108,7 +1103,7 @@ class StarPilotLongitudinalLayout(_SettingsPage):
|
|||||||
def _developer_feature_access(self) -> bool:
|
def _developer_feature_access(self) -> bool:
|
||||||
return (
|
return (
|
||||||
starpilot_state.car_state.hasOpenpilotLongitudinal and
|
starpilot_state.car_state.hasOpenpilotLongitudinal and
|
||||||
(gui_app.big_ui() or self._params.get_bool("DeveloperUI") or self._params.get_bool("GalaxyDeveloperMode"))
|
(self._params.get_bool("DeveloperUI") or self._params.get_bool("GalaxyDeveloperMode"))
|
||||||
)
|
)
|
||||||
|
|
||||||
def _speed_unit(self) -> str:
|
def _speed_unit(self) -> str:
|
||||||
|
|||||||
@@ -130,6 +130,9 @@ class VehicleSettingsManagerView(PanelManagerView):
|
|||||||
float(self._controller._params.get_int("LockDoorsTimer")),
|
float(self._controller._params.get_int("LockDoorsTimer")),
|
||||||
f"{self._controller._params.get_int('LockDoorsTimer')}s"),
|
f"{self._controller._params.get_int('LockDoorsTimer')}s"),
|
||||||
on_click=lambda: self._controller._on_select("LockDoorsTimer")))
|
on_click=lambda: self._controller._on_select("LockDoorsTimer")))
|
||||||
|
rows.append(SettingRow("ClusterOffset", "value", tr_noop("Dashboard Speed Offset"),
|
||||||
|
get_value=lambda: f"{self._controller._params.get_float('ClusterOffset'):.3f}x",
|
||||||
|
on_click=lambda: self._controller._on_select("ClusterOffset")))
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
def _combo_value(self, keys: tuple[str, ...]) -> str:
|
def _combo_value(self, keys: tuple[str, ...]) -> str:
|
||||||
@@ -717,6 +720,8 @@ class StarPilotVehicleSettingsLayout(_SettingsPage):
|
|||||||
self._on_select_model()
|
self._on_select_model()
|
||||||
elif key == "LockDoorsTimer":
|
elif key == "LockDoorsTimer":
|
||||||
self._show_lock_timer_selector()
|
self._show_lock_timer_selector()
|
||||||
|
elif key == "ClusterOffset":
|
||||||
|
self._show_offset_selector()
|
||||||
else:
|
else:
|
||||||
self._show_action_picker(key)
|
self._show_action_picker(key)
|
||||||
|
|
||||||
@@ -809,7 +814,7 @@ class StarPilotVehicleSettingsLayout(_SettingsPage):
|
|||||||
allowed_ids = set(range(9)) | {11, 12, 13, 14}
|
allowed_ids = set(range(9)) | {11, 12, 13, 14}
|
||||||
if key == "LKASButtonControl":
|
if key == "LKASButtonControl":
|
||||||
allowed_ids.add(9)
|
allowed_ids.add(9)
|
||||||
developer_access = gui_app.big_ui() or self._params.get_bool("DeveloperUI") or self._params.get_bool("GalaxyDeveloperMode")
|
developer_access = self._params.get_bool("DeveloperUI") or self._params.get_bool("GalaxyDeveloperMode")
|
||||||
options = [o for o in ACTION_OPTIONS
|
options = [o for o in ACTION_OPTIONS
|
||||||
if o["id"] in allowed_ids and
|
if o["id"] in allowed_ids and
|
||||||
(cs.hasOpenpilotLongitudinal or not o.get("requires_longitudinal", False)) and
|
(cs.hasOpenpilotLongitudinal or not o.get("requires_longitudinal", False)) and
|
||||||
@@ -838,6 +843,15 @@ class StarPilotVehicleSettingsLayout(_SettingsPage):
|
|||||||
self._params.get_int("LockDoorsTimer"), on_close,
|
self._params.get_int("LockDoorsTimer"), on_close,
|
||||||
labels=_lock_doors_timer_labels(), color=PANEL_STYLE.accent))
|
labels=_lock_doors_timer_labels(), color=PANEL_STYLE.accent))
|
||||||
|
|
||||||
|
def _show_offset_selector(self):
|
||||||
|
def on_close(res, val):
|
||||||
|
if res == DialogResult.CONFIRM:
|
||||||
|
self._params.put_float("ClusterOffset", float(val))
|
||||||
|
|
||||||
|
gui_app.push_widget(AetherSliderDialog(tr("Dashboard Speed Offset"), 1.000, 1.050, 0.001,
|
||||||
|
self._params.get_float("ClusterOffset"), on_close,
|
||||||
|
unit="x", color=PANEL_STYLE.accent))
|
||||||
|
|
||||||
def _get_display_make(self) -> str:
|
def _get_display_make(self) -> str:
|
||||||
make = self._params.get("CarMake") or ""
|
make = self._params.get("CarMake") or ""
|
||||||
if make:
|
if make:
|
||||||
|
|||||||
@@ -3653,6 +3653,17 @@
|
|||||||
"galaxy_only": true,
|
"galaxy_only": true,
|
||||||
"settings_tier": "simple"
|
"settings_tier": "simple"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "ClusterOffset",
|
||||||
|
"label": "Dashboard Speed Offset",
|
||||||
|
"description": "The speed offset openpilot uses to match the speed on the dashboard display.",
|
||||||
|
"data_type": "float",
|
||||||
|
"ui_type": "numeric",
|
||||||
|
"min": 1.0,
|
||||||
|
"max": 1.05,
|
||||||
|
"step": 0.001,
|
||||||
|
"settings_tier": "simple"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "SNGHack",
|
"key": "SNGHack",
|
||||||
"label": "Stop-and-Go Hack",
|
"label": "Stop-and-Go Hack",
|
||||||
@@ -4870,19 +4881,6 @@
|
|||||||
"is_parent_toggle": true,
|
"is_parent_toggle": true,
|
||||||
"settings_tier": "simple"
|
"settings_tier": "simple"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"key": "ClusterOffset",
|
|
||||||
"label": "Dashboard Speed Offset",
|
|
||||||
"description": "Multiplier for dashboard speed. 1x = no offset; 1.05x = 5% faster.",
|
|
||||||
"data_type": "float",
|
|
||||||
"ui_type": "numeric",
|
|
||||||
"unit": "x",
|
|
||||||
"min": 1.0,
|
|
||||||
"max": 1.05,
|
|
||||||
"step": 0.001,
|
|
||||||
"parent_key": "GalaxyDeveloperMode",
|
|
||||||
"settings_tier": "advanced"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "GalaxyMobileDefault",
|
"key": "GalaxyMobileDefault",
|
||||||
"label": "Use Galaxy (new) by Default",
|
"label": "Use Galaxy (new) by Default",
|
||||||
|
|||||||
@@ -880,7 +880,7 @@ class StarPilotVariables:
|
|||||||
toggle.car_model = car_model
|
toggle.car_model = car_model
|
||||||
|
|
||||||
self.migrate_prius_cluster_offset(str(toggle.car_model))
|
self.migrate_prius_cluster_offset(str(toggle.car_model))
|
||||||
toggle.cluster_offset = self.get_value("ClusterOffset", cast=float)
|
toggle.cluster_offset = self.get_value("ClusterOffset", cast=float, condition=toggle.car_make == "toyota")
|
||||||
|
|
||||||
toggle.longitudinal_mode_values = mode_values
|
toggle.longitudinal_mode_values = mode_values
|
||||||
toggle.experimental_mode = toggle.experimental_mode_available and not toggle.safe_mode and mode_values["ExperimentalMode"]
|
toggle.experimental_mode = toggle.experimental_mode_available and not toggle.safe_mode and mode_values["ExperimentalMode"]
|
||||||
@@ -989,8 +989,7 @@ class StarPilotVariables:
|
|||||||
toggle.static_pedals_on_ui = self.get_value("StaticPedalsOnUI", condition=toggle.pedals_on_ui)
|
toggle.static_pedals_on_ui = self.get_value("StaticPedalsOnUI", condition=toggle.pedals_on_ui)
|
||||||
toggle.rotating_wheel = self.get_value("RotatingWheel", condition=custom_ui)
|
toggle.rotating_wheel = self.get_value("RotatingWheel", condition=custom_ui)
|
||||||
|
|
||||||
big_ui = os.getenv("BIG", "0") == "1" or HARDWARE.get_device_type() in ("tici", "tizi")
|
toggle.developer_ui = self.get_value("DeveloperUI")
|
||||||
toggle.developer_ui = self.get_value("DeveloperUI") or big_ui
|
|
||||||
developer_metrics = self.get_value("DeveloperMetrics", condition=toggle.developer_ui)
|
developer_metrics = self.get_value("DeveloperMetrics", condition=toggle.developer_ui)
|
||||||
border_metrics = self.get_value("BorderMetrics", condition=developer_metrics)
|
border_metrics = self.get_value("BorderMetrics", condition=developer_metrics)
|
||||||
toggle.blind_spot_metrics = has_bsm and self.get_value("BlindSpotMetrics", condition=border_metrics)
|
toggle.blind_spot_metrics = has_bsm and self.get_value("BlindSpotMetrics", condition=border_metrics)
|
||||||
@@ -1043,7 +1042,7 @@ class StarPilotVariables:
|
|||||||
condition=toggle.car_make == "gm" and toggle.has_pedal and "BOLT" in toggle.car_model,
|
condition=toggle.car_make == "gm" and toggle.has_pedal and "BOLT" in toggle.car_model,
|
||||||
)
|
)
|
||||||
|
|
||||||
developer_feature_access = toggle.developer_ui or self.params.get_bool("GalaxyDeveloperMode")
|
developer_feature_access = self.params.get_bool("DeveloperUI") or self.params.get_bool("GalaxyDeveloperMode")
|
||||||
toggle.pulse_and_glide_available = toggle.openpilot_longitudinal and developer_feature_access
|
toggle.pulse_and_glide_available = toggle.openpilot_longitudinal and developer_feature_access
|
||||||
toggle.pulse_glide_speed_delta = self.get_value(
|
toggle.pulse_glide_speed_delta = self.get_value(
|
||||||
"PulseGlideSpeedDelta",
|
"PulseGlideSpeedDelta",
|
||||||
|
|||||||
@@ -293,22 +293,6 @@ def test_disabled_conditional_experimental_toggles_are_off(monkeypatch, tmp_path
|
|||||||
assert toggles.conditional_signal_lane_detection is False
|
assert toggles.conditional_signal_lane_detection is False
|
||||||
|
|
||||||
|
|
||||||
def test_big_ui_exposes_developer_toggles_without_persisting_developer_ui(monkeypatch, tmp_path):
|
|
||||||
params_cls = spv.Params
|
|
||||||
|
|
||||||
def isolated_params(_path=None, memory=False, return_defaults=False):
|
|
||||||
return params_cls(str(tmp_path / ("memory" if memory else "params")), return_defaults=return_defaults)
|
|
||||||
|
|
||||||
monkeypatch.setattr(spv, "Params", isolated_params)
|
|
||||||
monkeypatch.setattr(spv.HARDWARE, "get_device_type", lambda: "tici")
|
|
||||||
monkeypatch.delenv("BIG", raising=False)
|
|
||||||
|
|
||||||
variables = spv.StarPilotVariables()
|
|
||||||
|
|
||||||
assert variables.starpilot_toggles.developer_ui is True
|
|
||||||
assert variables.params_raw.get_bool("DeveloperUI") is False
|
|
||||||
|
|
||||||
|
|
||||||
def test_device_shutdown_hours_convert_directly_to_seconds():
|
def test_device_shutdown_hours_convert_directly_to_seconds():
|
||||||
assert spv.device_shutdown_seconds(6) == 6 * 60 * 60
|
assert spv.device_shutdown_seconds(6) == 6 * 60 * 60
|
||||||
assert spv.device_shutdown_seconds(0) == 60 * 60
|
assert spv.device_shutdown_seconds(0) == 60 * 60
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ const VEHICLE_SETTING_MAKES = {
|
|||||||
SubaruSNGManualParkingBrake: ["Subaru"],
|
SubaruSNGManualParkingBrake: ["Subaru"],
|
||||||
SubaruStopStartOff: ["Subaru"],
|
SubaruStopStartOff: ["Subaru"],
|
||||||
SubaruRedneckCruise: ["Subaru"],
|
SubaruRedneckCruise: ["Subaru"],
|
||||||
|
ClusterOffset: ["Lexus", "Toyota"],
|
||||||
SNGHack: ["Lexus", "Toyota"],
|
SNGHack: ["Lexus", "Toyota"],
|
||||||
ToyotaAutoHold: ["Lexus", "Toyota"],
|
ToyotaAutoHold: ["Lexus", "Toyota"],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ const VEHICLE_SETTING_MAKES = {
|
|||||||
SubaruSNGManualParkingBrake: ["Subaru"],
|
SubaruSNGManualParkingBrake: ["Subaru"],
|
||||||
SubaruStopStartOff: ["Subaru"],
|
SubaruStopStartOff: ["Subaru"],
|
||||||
SubaruRedneckCruise: ["Subaru"],
|
SubaruRedneckCruise: ["Subaru"],
|
||||||
|
ClusterOffset: ["Lexus", "Toyota"],
|
||||||
SNGHack: ["Lexus", "Toyota"],
|
SNGHack: ["Lexus", "Toyota"],
|
||||||
ToyotaAutoHold: ["Lexus", "Toyota"],
|
ToyotaAutoHold: ["Lexus", "Toyota"],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -345,31 +345,6 @@ def test_toyota_auto_hold_is_galaxy_only():
|
|||||||
assert setting["data_type"] == "bool"
|
assert setting["data_type"] == "bool"
|
||||||
|
|
||||||
|
|
||||||
def test_cluster_offset_is_in_galaxy_developer_section_only():
|
|
||||||
sections = _params_by_section(_layout())
|
|
||||||
assert "ClusterOffset" not in sections["Vehicle"]
|
|
||||||
setting = sections["Developer"]["ClusterOffset"]
|
|
||||||
|
|
||||||
assert setting["parent_key"] == "GalaxyDeveloperMode"
|
|
||||||
assert setting["settings_tier"] == "advanced"
|
|
||||||
assert setting["data_type"] == "float"
|
|
||||||
assert "1x = no offset" in setting["description"]
|
|
||||||
assert setting["unit"] == "x"
|
|
||||||
assert setting["min"] == 1.0
|
|
||||||
assert setting["max"] == 1.05
|
|
||||||
assert setting["step"] == 0.001
|
|
||||||
|
|
||||||
native_vehicle_settings = REPO_ROOT / "selfdrive/ui/layouts/settings/starpilot/vehicle.py"
|
|
||||||
native_source = native_vehicle_settings.read_text(encoding="utf-8")
|
|
||||||
assert 'SettingRow("ClusterOffset"' not in native_source
|
|
||||||
assert "def _show_offset_selector" not in native_source
|
|
||||||
|
|
||||||
for galaxy_source in (
|
|
||||||
REPO_ROOT / "starpilot/system/the_galaxy/assets/components/tools/device_settings.js",
|
|
||||||
REPO_ROOT / "starpilot/system/the_galaxy/assets/mobile/js/params.js",
|
|
||||||
):
|
|
||||||
assert "ClusterOffset:" not in galaxy_source.read_text(encoding="utf-8")
|
|
||||||
|
|
||||||
def test_human_acceleration_param_is_removed():
|
def test_human_acceleration_param_is_removed():
|
||||||
params_source = PARAM_KEYS_PATH.read_text(encoding="utf-8")
|
params_source = PARAM_KEYS_PATH.read_text(encoding="utf-8")
|
||||||
assert '{"HumanAcceleration",' not in params_source
|
assert '{"HumanAcceleration",' not in params_source
|
||||||
|
|||||||
@@ -690,11 +690,6 @@ assert(P.isSettingVisible(sec, sec.params[1], {}) === false, "advanced hidden (o
|
|||||||
assert(P.isSettingVisible(sec, sec.params[1], { GalaxyDeveloperMode: true }) === true, "advanced visible (on)")
|
assert(P.isSettingVisible(sec, sec.params[1], { GalaxyDeveloperMode: true }) === true, "advanced visible (on)")
|
||||||
assert(P.countAdvancedHiddenByDeveloperMode([sec], {}) === 1, "count hidden (off)")
|
assert(P.countAdvancedHiddenByDeveloperMode([sec], {}) === 1, "count hidden (off)")
|
||||||
assert(P.countAdvancedHiddenByDeveloperMode([sec], { GalaxyDeveloperMode: true }) === 0, "count hidden (on)")
|
assert(P.countAdvancedHiddenByDeveloperMode([sec], { GalaxyDeveloperMode: true }) === 0, "count hidden (on)")
|
||||||
const developer = { name: "Developer", params: [] }
|
|
||||||
const clusterOffset = { key: "ClusterOffset", parent_key: "GalaxyDeveloperMode", settings_tier: "advanced", data_type: "float" }
|
|
||||||
assert(P.isVehicleSettingVisible(developer, clusterOffset, { CarMake: "gm" }) === true, "cluster offset has no vehicle filter")
|
|
||||||
assert(P.isSettingVisible(developer, clusterOffset, { CarMake: "gm" }) === false, "cluster offset hidden without developer mode")
|
|
||||||
assert(P.isSettingVisible(developer, clusterOffset, { CarMake: "gm", GalaxyDeveloperMode: true }) === true, "cluster offset visible in developer mode")
|
|
||||||
const slider = { key: "DeviceShutdown", data_type: "int", min: 1, max: 30, step: 1 }
|
const slider = { key: "DeviceShutdown", data_type: "int", min: 1, max: 30, step: 1 }
|
||||||
assert(P.snapNumericToBoundsAndStep(17.9, P.numericBounds(slider, {}), 0) === 18, "snap")
|
assert(P.snapNumericToBoundsAndStep(17.9, P.numericBounds(slider, {}), 0) === 18, "snap")
|
||||||
assert(P.formatSliderValue(6, "1", 0, "DeviceShutdown") === "6 hours", "format")
|
assert(P.formatSliderValue(6, "1", 0, "DeviceShutdown") === "6 hours", "format")
|
||||||
|
|||||||
Reference in New Issue
Block a user