hardware_query/
hardware_info.rs

1use crate::{
2    BatteryInfo, CPUInfo, GPUInfo, HardwareQueryError,
3    MemoryInfo, NetworkInfo, NPUInfo, PCIDevice, Result, StorageInfo, ThermalInfo, TPUInfo, USBDevice,
4    ARMHardwareInfo, FPGAInfo, PowerProfile, VirtualizationInfo,
5};
6use serde::{Deserialize, Serialize};
7use std::time::{SystemTime, UNIX_EPOCH};
8use std::collections::HashMap;
9
10/// Complete system hardware information
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct HardwareInfo {
13    /// Timestamp when the hardware information was collected
14    pub timestamp: u64,
15    /// CPU information
16    pub cpu: CPUInfo,
17    /// GPU information (multiple GPUs supported)
18    pub gpus: Vec<GPUInfo>,
19    /// NPU information (Neural Processing Units)
20    pub npus: Vec<NPUInfo>,
21    /// TPU information (Tensor Processing Units)
22    pub tpus: Vec<TPUInfo>,
23    /// ARM-specific hardware information (if running on ARM)
24    pub arm_hardware: Option<ARMHardwareInfo>,
25    /// FPGA accelerators
26    pub fpgas: Vec<FPGAInfo>,
27    /// Memory information
28    pub memory: MemoryInfo,
29    /// Storage devices
30    pub storage_devices: Vec<StorageInfo>,
31    /// Network interfaces
32    pub network_interfaces: Vec<NetworkInfo>,
33    /// Battery information (if available)
34    pub battery: Option<BatteryInfo>,
35    /// Thermal sensors and fans
36    pub thermal: ThermalInfo,
37    /// PCI devices
38    pub pci_devices: Vec<PCIDevice>,
39    /// USB devices
40    pub usb_devices: Vec<USBDevice>,
41    /// Power consumption and efficiency profile
42    pub power_profile: Option<PowerProfile>,
43    /// Virtualization environment information
44    pub virtualization: VirtualizationInfo,
45}
46
47impl HardwareInfo {
48    /// Query all available hardware information
49    pub fn query() -> Result<Self> {
50        let timestamp = SystemTime::now()
51            .duration_since(UNIX_EPOCH)
52            .map_err(|e| HardwareQueryError::unknown(format!("Failed to get timestamp: {e}")))?
53            .as_secs();
54
55        Ok(Self {
56            timestamp,
57            cpu: CPUInfo::query()?,
58            gpus: GPUInfo::query_all()?,
59            npus: NPUInfo::query_all()?,
60            tpus: TPUInfo::query_all()?,
61            arm_hardware: ARMHardwareInfo::detect().ok().flatten(),
62            fpgas: FPGAInfo::detect_fpgas().unwrap_or_default(),
63            memory: MemoryInfo::query()?,
64            storage_devices: StorageInfo::query_all()?,
65            network_interfaces: NetworkInfo::query_all()?,
66            battery: BatteryInfo::query().ok(),
67            thermal: ThermalInfo::query()?,
68            pci_devices: PCIDevice::query_all()?,
69            usb_devices: USBDevice::query_all()?,
70            power_profile: PowerProfile::query().ok(),
71            virtualization: VirtualizationInfo::detect()?,
72        })
73    }
74
75    /// Get CPU information
76    pub fn cpu(&self) -> &CPUInfo {
77        &self.cpu
78    }
79
80    /// Get GPU information
81    pub fn gpus(&self) -> &[GPUInfo] {
82        &self.gpus
83    }
84
85    /// Get NPU information
86    pub fn npus(&self) -> &[NPUInfo] {
87        &self.npus
88    }
89
90    /// Get TPU information
91    pub fn tpus(&self) -> &[TPUInfo] {
92        &self.tpus
93    }
94
95    /// Get ARM hardware information (if available)
96    pub fn arm_hardware(&self) -> Option<&ARMHardwareInfo> {
97        self.arm_hardware.as_ref()
98    }
99
100    /// Get FPGA accelerator information
101    pub fn fpgas(&self) -> &[FPGAInfo] {
102        &self.fpgas
103    }
104
105    /// Get memory information
106    pub fn memory(&self) -> &MemoryInfo {
107        &self.memory
108    }
109
110    /// Get storage devices
111    pub fn storage_devices(&self) -> &[StorageInfo] {
112        &self.storage_devices
113    }
114
115    /// Get network interfaces
116    pub fn network_interfaces(&self) -> &[NetworkInfo] {
117        &self.network_interfaces
118    }
119
120    /// Get battery information (if available)
121    pub fn battery(&self) -> Option<&BatteryInfo> {
122        self.battery.as_ref()
123    }
124
125    /// Get thermal information
126    pub fn thermal(&self) -> &ThermalInfo {
127        &self.thermal
128    }
129
130    /// Get PCI devices
131    pub fn pci_devices(&self) -> &[PCIDevice] {
132        &self.pci_devices
133    }
134
135    /// Get USB devices
136    pub fn usb_devices(&self) -> &[USBDevice] {
137        &self.usb_devices
138    }
139
140    /// Get power profile information (if available)
141    pub fn power_profile(&self) -> Option<&PowerProfile> {
142        self.power_profile.as_ref()
143    }
144
145    /// Get virtualization information
146    pub fn virtualization(&self) -> &VirtualizationInfo {
147        &self.virtualization
148    }
149
150    /// Check if system is ARM-based
151    pub fn is_arm_system(&self) -> bool {
152        self.arm_hardware.is_some()
153    }
154
155    /// Check if system has FPGA accelerators
156    pub fn has_fpgas(&self) -> bool {
157        !self.fpgas.is_empty()
158    }
159
160    /// Check if running in a virtualized environment
161    pub fn is_virtualized(&self) -> bool {
162        self.virtualization.is_virtualized()
163    }
164
165    /// Check if running in a container
166    pub fn is_containerized(&self) -> bool {
167        self.virtualization.is_containerized()
168    }
169
170    /// Get estimated performance impact from virtualization (0.0 to 1.0)
171    pub fn virtualization_performance_impact(&self) -> f64 {
172        self.virtualization.get_performance_factor()
173    }
174
175    /// Get count of specialized accelerators (NPUs + TPUs + FPGAs)
176    pub fn accelerator_count(&self) -> usize {
177        self.npus.len() + self.tpus.len() + self.fpgas.len()
178    }
179
180    /// Get comprehensive accelerator information
181    pub fn accelerator_summary(&self) -> HashMap<String, usize> {
182        let mut summary = HashMap::new();
183        
184        if !self.npus.is_empty() {
185            summary.insert("NPUs".to_string(), self.npus.len());
186        }
187        if !self.tpus.is_empty() {
188            summary.insert("TPUs".to_string(), self.tpus.len());
189        }
190        if !self.fpgas.is_empty() {
191            summary.insert("FPGAs".to_string(), self.fpgas.len());
192        }
193        
194        summary
195    }
196
197    /// Export hardware information as JSON
198    pub fn to_json(&self) -> Result<String> {
199        serde_json::to_string_pretty(self).map_err(Into::into)
200    }
201
202    /// Import hardware information from JSON
203    pub fn from_json(json: &str) -> Result<Self> {
204        serde_json::from_str(json).map_err(Into::into)
205    }
206
207    /// Get a summary of the most important hardware information
208    pub fn summary(&self) -> HardwareSummary {
209        HardwareSummary {
210            cpu_model: format!("{} {}", self.cpu.vendor(), self.cpu.model_name()),
211            cpu_cores: self.cpu.physical_cores(),
212            cpu_threads: self.cpu.logical_cores(),
213            total_memory_gb: self.memory.total_gb(),
214            primary_gpu: self.gpus.first().map(|gpu| {
215                format!(
216                    "{} {} ({} GB)",
217                    gpu.vendor(),
218                    gpu.model_name(),
219                    gpu.memory_gb()
220                )
221            }),
222            storage_total_gb: self
223                .storage_devices
224                .iter()
225                .map(|storage| storage.capacity_gb())
226                .sum(),
227        }
228    }
229}
230
231/// Summary of key hardware specifications
232#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct HardwareSummary {
234    pub cpu_model: String,
235    pub cpu_cores: u32,
236    pub cpu_threads: u32,
237    pub total_memory_gb: f64,
238    pub primary_gpu: Option<String>,
239    pub storage_total_gb: f64,
240}
241
242impl std::fmt::Display for HardwareSummary {
243    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244        writeln!(f, "Hardware Summary:")?;
245        writeln!(
246            f,
247            "  CPU: {} ({} cores, {} threads)",
248            self.cpu_model, self.cpu_cores, self.cpu_threads
249        )?;
250        writeln!(f, "  Memory: {:.1} GB", self.total_memory_gb)?;
251        if let Some(gpu) = &self.primary_gpu {
252            writeln!(f, "  Primary GPU: {gpu}")?;
253        }
254        writeln!(f, "  Total Storage: {:.1} GB", self.storage_total_gb)?;
255        Ok(())
256    }
257}