feat(openwrt): add WAN diagnostics to get-status and UI
get_wan_status now returns: radio0_disabled, sta_iface (from iw dev), sta_state (operstate), assoc_ssid (actually associated SSID vs configured), and recent wifi_log lines from logread. The WAN panel shows a diagnostic grid when configured but not connected so the user can see exactly what's wrong without digging into server logs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
33b96f4acf
commit
a862877189
@ -54,6 +54,25 @@ pub fn get_wan_status(router: &Router) -> serde_json::Value {
|
||||
|
||||
let ssid = router.uci_get("wireless.wwan.ssid").unwrap_or_default();
|
||||
let encryption = router.uci_get("wireless.wwan.encryption").unwrap_or_default();
|
||||
let radio0_disabled = router
|
||||
.uci_get("wireless.radio0.disabled")
|
||||
.map(|v| v == "1")
|
||||
.unwrap_or(false);
|
||||
|
||||
// Find the active sta-mode interface and its association state
|
||||
let iw_out = router.run_ok("iw dev 2>/dev/null").unwrap_or_default();
|
||||
let (sta_iface, assoc_ssid) = parse_sta_iface(&iw_out);
|
||||
|
||||
// Interface operstate (up / down / absent)
|
||||
let sta_state = if !sta_iface.is_empty() {
|
||||
router
|
||||
.run_ok(&format!("cat /sys/class/net/{}/operstate 2>/dev/null", sta_iface))
|
||||
.unwrap_or_else(|_| "unknown".into())
|
||||
.trim()
|
||||
.to_string()
|
||||
} else {
|
||||
"absent".to_string()
|
||||
};
|
||||
|
||||
// Source IP for reaching 8.8.8.8 — empty if no default route yet
|
||||
let ip = router
|
||||
@ -62,15 +81,60 @@ pub fn get_wan_status(router: &Router) -> serde_json::Value {
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
// Recent wifi-related kernel/syslog lines for quick diagnosis
|
||||
let wifi_log = router
|
||||
.run_ok("logread 2>/dev/null | grep -iE 'wlan|wwan|wifi|assoc|deauth|auth fail|CTRL-EVENT|wpa_supplicant' | tail -8 2>/dev/null")
|
||||
.unwrap_or_default()
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
serde_json::json!({
|
||||
"configured": configured,
|
||||
"ssid": ssid,
|
||||
"encryption": encryption,
|
||||
"ip": ip,
|
||||
"internet": !ip.is_empty(),
|
||||
"configured": configured,
|
||||
"ssid": ssid,
|
||||
"assoc_ssid": assoc_ssid,
|
||||
"encryption": encryption,
|
||||
"ip": ip,
|
||||
"internet": !ip.is_empty(),
|
||||
"radio0_disabled": radio0_disabled,
|
||||
"sta_iface": sta_iface,
|
||||
"sta_state": sta_state,
|
||||
"wifi_log": wifi_log,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_sta_iface(iw_out: &str) -> (String, String) {
|
||||
let mut result_iface = String::new();
|
||||
let mut result_ssid = String::new();
|
||||
let mut current_iface = String::new();
|
||||
let mut current_type = String::new();
|
||||
let mut current_ssid = String::new();
|
||||
|
||||
for line in iw_out.lines() {
|
||||
let line = line.trim();
|
||||
if let Some(name) = line.strip_prefix("Interface ") {
|
||||
// Save previous interface if it was a sta
|
||||
if current_type == "managed" && result_iface.is_empty() {
|
||||
result_iface = current_iface.clone();
|
||||
result_ssid = current_ssid.clone();
|
||||
}
|
||||
current_iface = name.trim().to_string();
|
||||
current_type.clear();
|
||||
current_ssid.clear();
|
||||
} else if let Some(t) = line.strip_prefix("type ") {
|
||||
current_type = t.trim().to_string();
|
||||
} else if let Some(s) = line.strip_prefix("ssid ") {
|
||||
current_ssid = s.trim().to_string();
|
||||
}
|
||||
}
|
||||
// Handle last block
|
||||
if current_type == "managed" && result_iface.is_empty() {
|
||||
result_iface = current_iface;
|
||||
result_ssid = current_ssid;
|
||||
}
|
||||
|
||||
(result_iface, result_ssid)
|
||||
}
|
||||
|
||||
fn detect_radio(router: &Router) -> Result<String> {
|
||||
// radio0 is universal; verify it exists
|
||||
let out = router.uci_get("wireless.radio0").unwrap_or_default();
|
||||
|
||||
@ -33,9 +33,14 @@ interface TollGateStatus {
|
||||
interface WanStatus {
|
||||
configured: boolean
|
||||
ssid: string
|
||||
assoc_ssid: string
|
||||
encryption: string
|
||||
ip: string
|
||||
internet: boolean
|
||||
radio0_disabled: boolean
|
||||
sta_iface: string
|
||||
sta_state: string
|
||||
wifi_log: string
|
||||
}
|
||||
|
||||
interface RouterStatus {
|
||||
@ -356,7 +361,7 @@ onMounted(() => load())
|
||||
|
||||
<!-- Current status (idle) -->
|
||||
<template v-if="wanStep === 'idle' || wanStep === 'done'">
|
||||
<div v-if="status.wan?.configured" class="flex items-center gap-3">
|
||||
<div v-if="status.wan?.configured" class="flex items-center gap-3 mb-3">
|
||||
<span class="w-2 h-2 rounded-full inline-block flex-shrink-0"
|
||||
:class="status.wan.internet ? 'bg-green-400' : 'bg-yellow-400 animate-pulse'"></span>
|
||||
<div>
|
||||
@ -366,10 +371,44 @@ onMounted(() => load())
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-sm text-white/50">
|
||||
<div v-else class="text-sm text-white/50 mb-3">
|
||||
Not configured — router has no internet access.
|
||||
</div>
|
||||
<p v-if="wanStep === 'done'" class="mt-3 text-xs text-green-400">
|
||||
|
||||
<!-- Diagnostics (shown when not connected) -->
|
||||
<dl v-if="status.wan?.configured && !status.wan.internet"
|
||||
class="grid grid-cols-2 gap-x-4 gap-y-2 text-xs mt-1 mb-3 border-t border-white/10 pt-3">
|
||||
<div>
|
||||
<dt class="text-white/30 mb-0.5">Radio</dt>
|
||||
<dd :class="status.wan.radio0_disabled ? 'text-red-400' : 'text-green-400'">
|
||||
{{ status.wan.radio0_disabled ? 'disabled' : 'enabled' }}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-white/30 mb-0.5">Interface</dt>
|
||||
<dd class="text-white/70 font-mono">
|
||||
{{ status.wan.sta_iface || 'none' }}
|
||||
<span v-if="status.wan.sta_iface" class="ml-1"
|
||||
:class="status.wan.sta_state === 'up' ? 'text-green-400' : 'text-yellow-400'">
|
||||
({{ status.wan.sta_state }})
|
||||
</span>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-white/30 mb-0.5">Associated to</dt>
|
||||
<dd class="text-white/70">{{ status.wan.assoc_ssid || 'none' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-white/30 mb-0.5">Configured SSID</dt>
|
||||
<dd class="text-white/70">{{ status.wan.ssid || '—' }}</dd>
|
||||
</div>
|
||||
<div v-if="status.wan.wifi_log" class="col-span-2">
|
||||
<dt class="text-white/30 mb-1">Recent wifi log</dt>
|
||||
<dd class="font-mono text-white/50 text-[10px] leading-relaxed whitespace-pre-wrap break-all bg-black/20 rounded p-2">{{ status.wan.wifi_log }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<p v-if="wanStep === 'done'" class="mt-2 text-xs text-green-400">
|
||||
WAN configured. Router is connecting…
|
||||
</p>
|
||||
</template>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user