Include supported settings in Galaxy diagnostic reports

(cherry picked from commit 0466650e4a)
This commit is contained in:
AngusBell97
2026-09-10 21:17:33 +01:00
committed by firestar5683
parent 737c8499eb
commit 38c98cf9f7
3 changed files with 87 additions and 7 deletions
@@ -6,6 +6,7 @@ function formatValue(value) {
if (typeof value === "boolean") return value ? "On" : "Off"
if (typeof value === "number") return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(4)))
if (value === null || value === undefined) return "n/a"
if (typeof value === "object") return JSON.stringify(value)
const text = String(value).trim()
return text || "(empty)"
}
@@ -18,6 +19,7 @@ function formatLearnedValue(value) {
function valuesMatch(left, right) {
if (left === right) return true
if (left && right && typeof left === "object" && typeof right === "object") return JSON.stringify(left) === JSON.stringify(right)
if ((left === null || left === undefined) && (right === null || right === undefined)) return true
if (typeof left === "number" && typeof right === "number") return Math.abs(left - right) < 1e-9
const lt = String(left ?? "").trim()
@@ -39,6 +41,7 @@ export const TroubleshootPanel = {
busySection: "",
error: "",
onlyNonDefault: false,
search: "",
vehicleStatus: { available: false, summary: "", summarySeverity: "neutral", items: [] },
snapshot: [],
sections: [],
@@ -50,8 +53,7 @@ export const TroubleshootPanel = {
return this.sections.reduce((count, s) => count + (Array.isArray(s.items) ? s.items.filter((i) => !valuesMatch(i?.value, i?.defaultValue)).length : 0), 0)
},
visibleSections() {
if (!this.onlyNonDefault) return this.sections
return this.sections.filter((s) => (Array.isArray(s.items) ? s.items.filter((i) => !valuesMatch(i?.value, i?.defaultValue)).length : 0) > 0)
return this.sections.filter((section) => this.itemsVisible(section).length > 0)
},
},
mounted() { this.load() },
@@ -61,7 +63,9 @@ export const TroubleshootPanel = {
isChanged(item) { return !valuesMatch(item?.value, item?.defaultValue) },
itemsVisible(section) {
const items = Array.isArray(section?.items) ? section.items : []
return this.onlyNonDefault ? items.filter((i) => !valuesMatch(i?.value, i?.defaultValue)) : items
const query = this.search.trim().toLowerCase()
return items.filter((i) => (!this.onlyNonDefault || !valuesMatch(i?.value, i?.defaultValue)) &&
(!query || `${section.title} ${i.key} ${i.label} ${formatValue(i.value)}`.toLowerCase().includes(query)))
},
severity(sev) {
const s = String(sev || "neutral").toLowerCase()
@@ -167,6 +171,7 @@ export const TroubleshootPanel = {
<span class="gx-switch__thumb"></span>
</label>
</div>
<input class="gx-field gx-field--full" type="search" v-model="search" placeholder="Search settings or categories..." aria-label="Search diagnostics" />
<GxNotice v-if="error" tone="danger" :text="error" style="margin:var(--sp-2) 0 0;" />
<div class="gx-row__desc"><strong>Onroad:</strong> {{ isOnroad ? 'Yes' : 'No' }}</div>
<div class="gx-row__desc"><strong>Changed Settings:</strong> {{ countNonDefault }}</div>
@@ -0,0 +1,35 @@
from types import SimpleNamespace
from test_dashboard_stats import _load_server_module, FakeParams
def test_registry_sections_are_loggable_supported_and_read_only(monkeypatch):
s = _load_server_module()
monkeypatch.setattr(s, "params", FakeParams({"IsOnroad": False}))
monkeypatch.setattr(s, "_TROUBLESHOOT_SECTION_DEFINITIONS", [])
monkeypatch.setattr(s, "_get_param_type_info", lambda: (set(), {}))
monkeypatch.setattr(s, "_get_default_param_values", lambda: {})
monkeypatch.setattr(s, "_get_troubleshoot_learned_values", lambda: {})
monkeypatch.setattr(s, "_get_layout_param_metadata", lambda: {"Parent": {"label": "Parent menu"}})
monkeypatch.setattr(s, "_get_hardware_snapshot_items", lambda: [])
monkeypatch.setattr(s, "_build_vehicle_fault_status", lambda: {"summary": "preserved"})
monkeypatch.setattr(s, "_get_safety_snapshot_text", lambda: "stock safety")
monkeypatch.setattr(s, "_get_fingerprint_snapshot_text", lambda: "fixture")
monkeypatch.setattr(s.utilities, "get_current_lan_ip", lambda: "127.0.0.1")
monkeypatch.setattr(s, "_safe_params_get", lambda *args, **kwargs: "")
keys = ["NewSetting", "Secret", "RivianAngle", "TeslaWakeOnCAN", "ControllerActionSlots"]
monkeypatch.setattr(s, "starpilot_default_params", [(key, None, None, None) for key in keys])
monkeypatch.setattr(s, "_params_raw", SimpleNamespace(get_key_flag=lambda key: s.ParamKeyFlag.DONT_LOG if key == "Secret" else 0))
monkeypatch.setattr(s, "_get_has_rivian_angle_harness", lambda: False)
monkeypatch.setattr(s, "supports_tesla_can_wake", lambda params: False)
monkeypatch.setattr(s, "load_settings_catalog", lambda: [{"name": "Category", "params": [
{"key": "NewSetting", "parent_key": "Parent"}, {"key": "NewSetting"},
{"key": "Secret"}, {"key": "Missing"}, {"key": "TeslaWakeOnCAN"},
{"key": "RivianAngle", "requires_capability": "HasRivianAngleHarness"}]}])
monkeypatch.setattr(s, "_build_troubleshoot_section_payload", lambda d, *args: {**d, "items": [{"key": k} for k in d["keys"]], "resettable": True})
result = s._build_troubleshoot_payload()
assert result["vehicleStatus"]["summary"] == "preserved"
assert result["snapshot"][0]["value"] == "stock safety"
sections = result["sections"]
assert [k for section in sections for k in section["keys"]] == ["ControllerActionSlots", "NewSetting"]
assert sections[1]["title"] == "Category Parent menu"
assert all(section["resettable"] is False for section in sections)
+44 -4
View File
@@ -1957,22 +1957,22 @@ _RUNTIME_DEFAULT_ZERO_OK_KEYS = {
_TROUBLESHOOT_SECTION_DEFINITIONS = [
{
"id": "personality_settings",
"title": "Personality Profile Settings",
"title": "Longitudinal (Speed & Following) Driving Personalities",
"keys": _TROUBLESHOOT_PERSONALITY_KEYS,
},
{
"id": "cem_settings",
"title": "CEM Settings",
"title": "Longitudinal (Speed & Following) Longitudinal control mode",
"keys": _TROUBLESHOOT_CEM_KEYS,
},
{
"id": "advanced_lateral_tuning",
"title": "Advanced Lateral Tuning",
"title": "Lateral (Steering) Advanced Lateral Tuning",
"keys": _TROUBLESHOOT_ADVANCED_LATERAL_KEYS,
},
{
"id": "advanced_longitudinal_tuning",
"title": "Advanced Longitudinal Tuning",
"title": "Longitudinal (Speed & Following) Advanced Longitudinal Tuning",
"keys": _TROUBLESHOOT_ADVANCED_LONGITUDINAL_KEYS,
},
]
@@ -4514,6 +4514,46 @@ def _build_troubleshoot_payload():
for section_definition in _TROUBLESHOOT_SECTION_DEFINITIONS
]
# Use the same category and parent metadata as Settings, rather than a second short list.
shown = {item['key'] for section in sections for item in section['items']}
registered = {key for key, *_ in starpilot_default_params}
for category in load_settings_catalog() or []:
groups = {}
for entry in category.get('params', []):
key = entry.get('key')
if key in shown or key not in registered or key.startswith('LaneCentering') or key == 'LaneCenterOffset':
continue
if (entry.get("requires_capability") == "HasRivianAngleHarness" and not _get_has_rivian_angle_harness()):
continue
if key == "TeslaWakeOnCAN" and not supports_tesla_can_wake(params):
continue
if _params_raw.get_key_flag(key) & ParamKeyFlag.DONT_LOG:
continue
parent = entry.get('parent_key')
title = category['name']
if parent:
title += ' ' + str(layout_metadata.get(parent, {}).get('label', parent))
groups.setdefault(title, []).append(key)
shown.add(key)
for title, keys in groups.items():
section = _build_troubleshoot_section_payload({'id': 'catalog_' + keys[0], 'title': title, 'keys': keys},
value_types, default_values, layout_metadata, learned_values)
section['resettable'] = False
sections.append(section)
for title, keys in [
('Bluetooth Controllers', ['BluetoothEnabled', 'BluetoothDisconnectControllersOffroad', 'WheelControlsEnabled', 'ControllerActionSlots', 'WheelControlMappings']),
('Longitudinal (Speed & Following) Longitudinal control mode', ['ExperimentalMode', 'ConditionalExperimental', 'ConditionalChill', 'LongitudinalPersonality']),
('Model Manager', ['Model', 'ActiveBigModel', 'ActiveSmallModel', 'ModelSortMode', 'UserFavorites'])]:
keys = [key for key in keys if key in registered and key not in shown
and not (_params_raw.get_key_flag(key) & ParamKeyFlag.DONT_LOG)]
if keys:
section = _build_troubleshoot_section_payload({'id': 'extra_' + keys[0], 'title': title, 'keys': keys},
value_types, default_values, layout_metadata, learned_values)
section['resettable'] = False
sections.append(section)
shown.update(keys)
sections.sort(key=lambda section: section["title"])
return _sanitize_json_value({
"vehicleStatus": _build_vehicle_fault_status(),
"snapshot": snapshot_items,