Skip to main content

heldar_kernel/routes/
discovery.rs

1use axum::extract::State;
2use axum::routing::post;
3use axum::{Json, Router};
4use serde_json::{json, Value};
5
6use crate::error::{AppError, AppResult};
7use crate::services::discovery::{self, DiscoverOptions};
8use crate::state::AppState;
9
10pub fn router() -> Router<AppState> {
11    Router::new().route("/api/v1/discover", post(discover_handler))
12}
13
14/// Scan a network range for cameras; optionally verify credentials and auto-register them.
15async fn discover_handler(
16    State(st): State<AppState>,
17    Json(opts): Json<DiscoverOptions>,
18) -> AppResult<Json<Value>> {
19    let devices = discovery::discover(&st.pool, &st.cfg, &st.http, &opts)
20        .await
21        .map_err(AppError::BadRequest)?;
22
23    let mut added: Vec<String> = Vec::new();
24    if opts.auto_add {
25        for d in devices
26            .iter()
27            .filter(|d| d.verified && !d.already_registered)
28        {
29            match discovery::add_device(&st.pool, d).await {
30                Ok(id) => {
31                    st.recorder.reconcile(&id).await;
32                    added.push(id);
33                }
34                Err(e) => {
35                    tracing::error!(addr = %d.address, error = %e, "discover: auto-add failed")
36                }
37            }
38        }
39    }
40
41    Ok(Json(json!({
42        "scanned": opts.targets,
43        "found": devices.len(),
44        "verified": devices.iter().filter(|d| d.verified).count(),
45        "added": added,
46        "devices": devices,
47    })))
48}