use std::time::Duration;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use nalgebra::DVector;
use anyhow::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SensorType {
ThermalImager, ThermalArray, Thermistor, Pyrometer,
Geophone, Accelerometer, Seismograph, Piezoelectric,
EMFProbe, TriField, GaussMeter, FluxGate, SQUIDMagnetometer,
Ultrasonic, Infrasound, FullSpectrum, ParabolicMic, ContactMic, MicArray,
Barometer, Hygrometer, Anemometer, IonCounter, VOCSensor, ParticulateSensor,
GeigerCounter, Scintillator, NeutronDetector, DosimeterArray,
LightMeter, UVSensor, IRDetector, Spectrometer, LiDAR, LaserGrid, NightVision,
SDRReceiver, SpectrumAnalyzer, WiFiScanner, EMIDetector,
CapacitiveSensor, StaticMeter, FieldMill, CurrentClamp,
IonChamber, CoronaDetector, PlasmaProbe,
QRNG, ThermalNoise, ShotNoise, ZenerDiode,
Custom(u32), }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SensorStatus {
Disconnected,
Connecting,
Connected,
Calibrating,
Active,
Error,
Maintenance,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CalibrationData {
pub offset: Vec<f64>,
pub scale: Vec<f64>,
pub noise_floor: f64,
pub timestamp: DateTime<Utc>,
pub temperature: Option<f64>,
pub notes: String,
pub signature: Vec<u8>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SensorReading {
pub sensor_id: String,
pub sensor_type: SensorType,
pub timestamp: DateTime<Utc>,
pub sequence: u64,
pub data: Vec<f64>,
pub dimensions: Vec<usize>,
pub unit: String,
pub sample_rate: f64,
pub quality: f32,
pub position: Option<[f64; 3]>, pub orientation: Option<[f64; 3]>, }
impl SensorReading {
pub fn new(sensor_id: &str, sensor_type: SensorType, data: Vec<f64>) -> Self {
Self {
sensor_id: sensor_id.to_string(),
sensor_type,
timestamp: Utc::now(),
sequence: 0,
data,
dimensions: vec![],
unit: String::new(),
sample_rate: 0.0,
quality: 1.0,
position: None,
orientation: None,
}
}
pub fn as_vector(&self) -> DVector<f64> {
DVector::from_vec(self.data.clone())
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
#[async_trait]
pub trait Sensor: Send + Sync {
fn id(&self) -> &str;
fn sensor_type(&self) -> SensorType;
fn status(&self) -> SensorStatus;
async fn connect(&mut self) -> Result<()>;
async fn disconnect(&mut self) -> Result<()>;
async fn calibrate(&mut self) -> Result<CalibrationData>;
async fn read(&mut self) -> Result<SensorReading>;
fn sample_rate(&self) -> f64;
fn set_sample_rate(&mut self, rate: f64) -> Result<()>;
fn config(&self) -> serde_json::Value;
fn set_config(&mut self, config: serde_json::Value) -> Result<()>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SensorHealth {
pub sensor_id: String,
pub status: SensorStatus,
pub uptime_seconds: u64,
pub readings_count: u64,
pub error_count: u64,
pub last_error: Option<String>,
pub signal_quality: f32,
pub noise_level: f64,
pub temperature: Option<f64>,
pub battery_level: Option<f32>,
}