diff --git a/agent/src/main.rs b/agent/src/main.rs index 833a47d..8e97b03 100644 --- a/agent/src/main.rs +++ b/agent/src/main.rs @@ -1,9 +1,133 @@ -use nanometrics_agent::config; +use nanometrics_agent::{config, metrics, payload, transport}; +use sysinfo::{Components, Disks, Networks, System}; +use std::time::{Duration, Instant}; +use std::sync::mpsc; + +fn get_local_ip() -> String { + use std::net::UdpSocket; + if let Ok(s) = UdpSocket::bind("0.0.0.0:0") { + if s.connect("8.8.8.8:80").is_ok() { + if let Ok(addr) = s.local_addr() { + return addr.ip().to_string(); + } + } + } + "0.0.0.0".to_string() +} + +fn apply_config_update(cfg: &mut config::Config, data: &[u8]) { + if let Ok(new_cfg) = serde_json::from_slice::(data) { + cfg.metrics = new_cfg.metrics; + eprintln!("[config] mis à jour depuis le serveur"); + } +} fn main() { let cfg_path = std::env::args() .nth(1) .unwrap_or_else(|| "config.toml".to_string()); - let _cfg = config::load(std::path::Path::new(&cfg_path)); - println!("nanometrics-agent starting"); + let mut cfg = config::load(std::path::Path::new(&cfg_path)) + .expect("Impossible de charger config.toml"); + + let hostname = System::host_name().unwrap_or_else(|| "unknown".to_string()); + let ip = get_local_ip(); + + let mut sys = System::new(); + let mut networks = Networks::new_with_refreshed_list(); + let mut disks = Disks::new_with_refreshed_list(); + let mut components = Components::new_with_refreshed_list(); + + let udp_sender = if cfg.protocols.udp.enabled { + Some(transport::udp::UdpSender::new(&cfg.server.ip, cfg.server.port)) + } else { + None + }; + + let (incoming_tx, incoming_rx) = mpsc::channel::(); + let mqtt_client = if cfg.protocols.mqtt.enabled { + Some(transport::mqtt::start(&hostname, &cfg.protocols.mqtt, incoming_tx)) + } else { + None + }; + + let mut last_slow = Instant::now(); + let mut last_medium = Instant::now(); + let mut first_medium = true; + let mut first_slow = true; + + loop { + let now = Instant::now(); + + while let Ok(transport::mqtt::MqttIncoming::ConfigUpdate(data)) = incoming_rx.try_recv() { + apply_config_update(&mut cfg, &data); + } + + sys.refresh_cpu_usage(); + sys.refresh_memory(); + + let mut m = payload::AgentMetrics { + hostname: hostname.clone(), + ip: ip.clone(), + status: "online".to_string(), + cpu_percent: Some(metrics::cpu::get(&sys)), + ..Default::default() + }; + + let (mem_used, mem_free, mem_total) = metrics::memory::get(&sys); + m.memory_used = Some(mem_used); + m.memory_free = Some(mem_free); + m.memory_total = Some(mem_total); + + if first_medium || now.duration_since(last_medium).as_secs() >= 10 { + networks.refresh(); + components.refresh(); + let (rx, tx) = metrics::network::get(&networks); + if cfg.metrics.network.udp || cfg.metrics.network.mqtt { + m.network_rx = Some(rx); + m.network_tx = Some(tx); + } + if cfg.metrics.uptime.udp || cfg.metrics.uptime.mqtt { + m.uptime = Some(metrics::uptime::get()); + } + if cfg.metrics.temperature.udp || cfg.metrics.temperature.mqtt { + m.temperature = metrics::temperature::get(&components); + } + last_medium = now; + first_medium = false; + } + + if first_slow || now.duration_since(last_slow).as_secs() >= 60 { + disks.refresh(); + if cfg.metrics.disk.udp || cfg.metrics.disk.mqtt { + let (used, free, total) = metrics::disk::get(&disks); + m.hdd_used = Some(used); + m.hdd_free = Some(free); + m.hdd_total = Some(total); + } + if cfg.metrics.smart.udp || cfg.metrics.smart.mqtt { + m.smart = metrics::smart::collect(); + } + last_slow = now; + first_slow = false; + } + + let json = serde_json::to_string(&m).expect("sérialisation JSON impossible"); + + if let Some(ref udp) = udp_sender { + udp.send(&json); + } + + if let Some(ref client) = mqtt_client { + if cfg.protocols.mqtt.enabled { + transport::mqtt::publish_metrics( + client, + &cfg.protocols.mqtt.topic_base, + &hostname, + &json, + ); + } + } + + std::thread::sleep(Duration::from_secs(2)); + } }