troubleshoot
This commit is contained in:
@@ -67,6 +67,64 @@
|
||||
margin: 6px 0 0;
|
||||
}
|
||||
|
||||
.troubleshootFaultSummary {
|
||||
margin: 0 0 12px;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.troubleshootFaultGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.troubleshootFaultItem {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--sidebar-border-color);
|
||||
border-radius: var(--border-radius-md);
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.troubleshootFaultLabel {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.troubleshootStatusBadge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
border-radius: 999px;
|
||||
padding: 4px 10px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.02em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.troubleshootStatusBadgeOk {
|
||||
background: rgba(64, 201, 124, 0.18);
|
||||
color: #b8ffd4;
|
||||
}
|
||||
|
||||
.troubleshootStatusBadgeWarn {
|
||||
background: rgba(245, 188, 87, 0.18);
|
||||
color: #ffe2a3;
|
||||
}
|
||||
|
||||
.troubleshootStatusBadgeFault {
|
||||
background: rgba(217, 90, 123, 0.2);
|
||||
color: #ffd7e2;
|
||||
}
|
||||
|
||||
.troubleshootStatusBadgeNeutral {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: rgba(255, 255, 255, 0.88);
|
||||
}
|
||||
|
||||
.troubleshootSectionHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -3,6 +3,12 @@ import { html, reactive } from "/assets/vendor/arrow-core.js"
|
||||
const state = reactive({
|
||||
loading: true,
|
||||
error: "",
|
||||
vehicleStatus: {
|
||||
available: false,
|
||||
summary: "",
|
||||
summarySeverity: "neutral",
|
||||
items: [],
|
||||
},
|
||||
snapshot: [],
|
||||
sections: [],
|
||||
isOnroad: false,
|
||||
@@ -74,12 +80,25 @@ function countNonDefaultItems() {
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function statusBadgeClass(severity) {
|
||||
const safeSeverity = String(severity || "neutral").trim().toLowerCase()
|
||||
return `troubleshootStatusBadge troubleshootStatusBadge${safeSeverity.charAt(0).toUpperCase()}${safeSeverity.slice(1)}`
|
||||
}
|
||||
|
||||
function buildReportText() {
|
||||
const lines = []
|
||||
lines.push("StarPilot Troubleshoot Report")
|
||||
lines.push(`Generated: ${new Date().toISOString()}`)
|
||||
lines.push(`Onroad: ${state.isOnroad ? "Yes" : "No"}`)
|
||||
lines.push(`Only non-default values: ${state.showNonDefaultOnly ? "Yes" : "No"}`)
|
||||
if (state.vehicleStatus?.summary) {
|
||||
lines.push("")
|
||||
lines.push("Vehicle Fault Status")
|
||||
lines.push(`Summary: ${state.vehicleStatus.summary}`)
|
||||
for (const item of state.vehicleStatus.items || []) {
|
||||
lines.push(`- ${item.label}: ${formatValue(item.value)}`)
|
||||
}
|
||||
}
|
||||
lines.push("")
|
||||
lines.push("Snapshot")
|
||||
for (const item of state.snapshot) {
|
||||
@@ -133,6 +152,12 @@ async function fetchTroubleshoot(showToast = false) {
|
||||
|
||||
state.snapshot = Array.isArray(payload.snapshot) ? payload.snapshot : []
|
||||
state.sections = Array.isArray(payload.sections) ? payload.sections : []
|
||||
state.vehicleStatus = {
|
||||
available: !!payload.vehicleStatus?.available,
|
||||
summary: String(payload.vehicleStatus?.summary || ""),
|
||||
summarySeverity: String(payload.vehicleStatus?.summarySeverity || "neutral"),
|
||||
items: Array.isArray(payload.vehicleStatus?.items) ? payload.vehicleStatus.items : [],
|
||||
}
|
||||
state.isOnroad = !!payload.isOnroad
|
||||
state.error = ""
|
||||
|
||||
@@ -234,6 +259,24 @@ export function Troubleshoot() {
|
||||
<p class="troubleshootStatusLine"><strong>Changed Settings:</strong> ${() => countNonDefaultItems()}</p>
|
||||
</div>
|
||||
|
||||
<div class="troubleshootCard">
|
||||
<div class="troubleshootSectionHeader">
|
||||
<h3>Vehicle Fault Status</h3>
|
||||
<span class="${() => statusBadgeClass(state.vehicleStatus?.available ? "ok" : state.vehicleStatus?.summarySeverity || "neutral")}">
|
||||
${() => state.vehicleStatus?.available ? "Live" : "Unavailable"}
|
||||
</span>
|
||||
</div>
|
||||
<p class="troubleshootFaultSummary">${() => state.vehicleStatus?.summary || "Vehicle fault status unavailable."}</p>
|
||||
<div class="troubleshootFaultGrid">
|
||||
${() => (state.vehicleStatus?.items || []).map((item) => html`
|
||||
<div class="troubleshootFaultItem">
|
||||
<div class="troubleshootFaultLabel">${item.label}</div>
|
||||
<div class="${() => statusBadgeClass(item.severity)}">${formatValue(item.value)}</div>
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="troubleshootCard">
|
||||
<h3>Snapshot</h3>
|
||||
<div class="troubleshootHeaderRow troubleshootHeaderRowSnapshot">
|
||||
|
||||
@@ -2077,6 +2077,91 @@ def _snapshot_bool_text(value):
|
||||
return "No"
|
||||
return "Unavailable"
|
||||
|
||||
def _build_vehicle_fault_status():
|
||||
unavailable_items = [
|
||||
{"label": "Cruise Fault", "value": "Unavailable", "severity": "neutral"},
|
||||
{"label": "LKAS Fault", "value": "Unavailable", "severity": "neutral"},
|
||||
{"label": "CAN Valid", "value": "Unavailable", "severity": "neutral"},
|
||||
{"label": "Cruise Available", "value": "Unavailable", "severity": "neutral"},
|
||||
{"label": "Cruise Engaged", "value": "Unavailable", "severity": "neutral"},
|
||||
]
|
||||
|
||||
is_onroad = params.get_bool("IsOnroad")
|
||||
unavailable_summary = "Vehicle fault status is unavailable while offroad."
|
||||
unavailable_severity = "neutral"
|
||||
if is_onroad:
|
||||
unavailable_summary = "Waiting for live vehicle fault status..."
|
||||
unavailable_severity = "warn"
|
||||
|
||||
try:
|
||||
sm = messaging.SubMaster(["carState"], poll="carState")
|
||||
sm.update(100)
|
||||
has_live_car_state = sm.seen["carState"] and sm.alive["carState"] and sm.valid["carState"]
|
||||
if not has_live_car_state:
|
||||
return {
|
||||
"available": False,
|
||||
"summary": unavailable_summary,
|
||||
"summarySeverity": unavailable_severity,
|
||||
"items": unavailable_items,
|
||||
}
|
||||
|
||||
car_state = sm["carState"]
|
||||
cruise_state = getattr(car_state, "cruiseState", None)
|
||||
|
||||
cruise_faulted = bool(getattr(car_state, "accFaulted", False))
|
||||
steer_fault_temporary = bool(getattr(car_state, "steerFaultTemporary", False))
|
||||
steer_fault_permanent = bool(getattr(car_state, "steerFaultPermanent", False))
|
||||
can_valid = bool(getattr(car_state, "canValid", False))
|
||||
cruise_available = bool(getattr(cruise_state, "available", False)) if cruise_state is not None else None
|
||||
cruise_enabled = bool(getattr(cruise_state, "enabled", False)) if cruise_state is not None else None
|
||||
|
||||
if steer_fault_permanent:
|
||||
lkas_fault_value = "Permanent"
|
||||
lkas_fault_severity = "fault"
|
||||
elif steer_fault_temporary:
|
||||
lkas_fault_value = "Temporary"
|
||||
lkas_fault_severity = "warn"
|
||||
else:
|
||||
lkas_fault_value = "Clear"
|
||||
lkas_fault_severity = "ok"
|
||||
|
||||
active_statuses = []
|
||||
if cruise_faulted:
|
||||
active_statuses.append("cruise fault")
|
||||
if steer_fault_permanent:
|
||||
active_statuses.append("permanent LKAS fault")
|
||||
elif steer_fault_temporary:
|
||||
active_statuses.append("temporary LKAS fault")
|
||||
if not can_valid:
|
||||
active_statuses.append("CAN invalid")
|
||||
|
||||
if active_statuses:
|
||||
summary = "Active status: " + ", ".join(active_statuses) + "."
|
||||
summary_severity = "fault" if ("cruise fault" in active_statuses or "permanent LKAS fault" in active_statuses or "CAN invalid" in active_statuses) else "warn"
|
||||
else:
|
||||
summary = "No active cruise or LKAS faults detected."
|
||||
summary_severity = "ok"
|
||||
|
||||
return {
|
||||
"available": True,
|
||||
"summary": summary,
|
||||
"summarySeverity": summary_severity,
|
||||
"items": [
|
||||
{"label": "Cruise Fault", "value": "Faulted" if cruise_faulted else "Clear", "severity": "fault" if cruise_faulted else "ok"},
|
||||
{"label": "LKAS Fault", "value": lkas_fault_value, "severity": lkas_fault_severity},
|
||||
{"label": "CAN Valid", "value": "Yes" if can_valid else "No", "severity": "ok" if can_valid else "fault"},
|
||||
{"label": "Cruise Available", "value": "Yes" if cruise_available else "No", "severity": "ok" if cruise_available else "neutral"},
|
||||
{"label": "Cruise Engaged", "value": "Yes" if cruise_enabled else "No", "severity": "ok" if cruise_enabled else "neutral"},
|
||||
],
|
||||
}
|
||||
except Exception:
|
||||
return {
|
||||
"available": False,
|
||||
"summary": unavailable_summary,
|
||||
"summarySeverity": unavailable_severity,
|
||||
"items": unavailable_items,
|
||||
}
|
||||
|
||||
def _get_starpilot_toggles_snapshot():
|
||||
raw_toggles = _safe_params_get_live_raw("StarPilotToggles")
|
||||
if not raw_toggles:
|
||||
@@ -2260,6 +2345,7 @@ def _build_troubleshoot_payload():
|
||||
]
|
||||
|
||||
return {
|
||||
"vehicleStatus": _build_vehicle_fault_status(),
|
||||
"snapshot": snapshot_items,
|
||||
"sections": sections,
|
||||
"isOnroad": params.get_bool("IsOnroad"),
|
||||
|
||||
Reference in New Issue
Block a user