diff --git a/core/openwrt/src/wan.rs b/core/openwrt/src/wan.rs index 4620b131..35867d74 100644 --- a/core/openwrt/src/wan.rs +++ b/core/openwrt/src/wan.rs @@ -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 { // radio0 is universal; verify it exists let out = router.uci_get("wireless.radio0").unwrap_or_default(); diff --git a/neode-ui/src/views/server/OpenWrtGateway.vue b/neode-ui/src/views/server/OpenWrtGateway.vue index 7446d2a9..4cb9c72f 100644 --- a/neode-ui/src/views/server/OpenWrtGateway.vue +++ b/neode-ui/src/views/server/OpenWrtGateway.vue @@ -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())