use axum::{Json, http::StatusCode}; use chrono::Utc; use log::error; use serde::Serialize; use utoipa::ToSchema; use crate::scanners::mdns::status as mdns_scanner_status; #[derive(Serialize, ToSchema)] pub struct MdnsScannerStatusResponse { pub is_listening: bool, /// Seconds the listener has been running (only set when is_listening is true) pub listening_for_seconds: Option, /// Total device announcements processed since the listener started pub devices_seen: u64, /// Seconds since the last device was seen (None if none seen yet) pub last_device_seen_seconds_ago: Option, } #[utoipa::path( get, path = "/api/mdns_scanner/status", tag = "mdns_scanner", responses( (status = 200, description = "mDNS scanner status", body = MdnsScannerStatusResponse), (status = 500, description = "Internal server error"), ), security(("bearer_auth" = [])) )] pub async fn status() -> Result, StatusCode> { let snapshot = match mdns_scanner_status::get() { Some(s) => s, None => { error!("mDNS scanner status not initialized"); return Err(StatusCode::INTERNAL_SERVER_ERROR); } }; let now = Utc::now(); let listening_for_seconds = if snapshot.is_listening { snapshot .listening_since .map(|t| (now - t).num_milliseconds() as f64 / 1000.0) } else { None }; let last_device_seen_seconds_ago = snapshot .last_discovery_at .map(|t| ((now - t).num_milliseconds() as f64 / 1000.0).max(0.0)); Ok(Json(MdnsScannerStatusResponse { is_listening: snapshot.is_listening, listening_for_seconds, devices_seen: snapshot.devices_discovered, last_device_seen_seconds_ago, })) }