use diesel::prelude::*; use std::f64::consts::PI; use crate::{unit_conversion::UnitsConversion, Point}; #[derive(Debug, Clone, Default, Queryable, Selectable, serde::Serialize, serde::Deserialize)] #[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(table_name = crate::schema::antennas)] pub struct Antenna { pub id: String, pub tssi: f64, pub pos_x: f64, pub pos_y: f64, pub pos_z: f64, pub comment: Option, } #[derive(Debug, Clone, Copy, Insertable, AsChangeset, serde::Deserialize)] #[diesel(table_name = crate::schema::antennas)] pub struct NewAntenna<'a> { pub id: &'a str, pub tssi: f64, pub pos_x: f64, pub pos_y: f64, pub pos_z: f64, pub comment: Option<&'a str>, } impl Antenna { const C: f64 = 2.99e8; const F: f64 = 2.4e9; const λ: f64 = Self::C / Self::F; pub fn new(id: &str, tssi: f64, coord: Point) -> Antenna { Antenna { id: id.into(), comment: None, pos_x: coord.x, pos_y: coord.y, pos_z: 0.0, tssi, } } pub fn coord(&self) -> Point { Point::new(self.pos_x, self.pos_y) } pub fn get_rssi(&self, distance: f64) -> f64 { #[allow(non_snake_case)] // Free Space Path Loss let FSPL = (((distance * 4.0 * PI) / Self::λ).powi(2)).to_dB(); self.tssi - FSPL } #[allow(non_snake_case)] pub fn get_distance_with_dBm(&self, rssi_dBm: f64) -> f64 { let loss = self.tssi.dBm_to_W() / rssi_dBm.dBm_to_W(); let distance = (loss.sqrt() * Self::λ) / (4.0 * PI); distance.abs() } #[allow(non_snake_case)] pub fn get_distance_with_W(&self, rssi_W: f64) -> f64 { let loss = self.tssi.dBm_to_W() / rssi_W; let distance = (loss.sqrt() * Self::λ) / (4.0 * PI); distance.abs() } } #[test] fn test() { let tssi = 0.0; // dBm let a = Antenna::new("AB:CD:EF:12:34:56", tssi, Point { x: 0.0, y: 0.0 }); // Known Attenuation values for 2.4GHz // 5 meter = 54.02 dB = 3.96e-9 W // 10 meter = 60.04 dB = 9.91e-10 W // 20 meter = 66.06 dB = 2.48e-10 W print!("Testing Antenna::get_rssi()"); assert!(f64::abs(-54.02 - a.get_rssi(5.0)) < 0.1); assert!(f64::abs(-60.04 - a.get_rssi(10.0)) < 0.1); assert!(f64::abs(-66.06 - a.get_rssi(20.0)) < 0.1); println!(" ... ok"); print!("Testing Antenna::get_distance_with_dBm()"); assert!(f64::abs(5.0 - a.get_distance_with_dBm(-54.02)) < 0.5); assert!(f64::abs(10.0 - a.get_distance_with_dBm(-60.04)) < 0.5); assert!(f64::abs(20.0 - a.get_distance_with_dBm(-66.06)) < 0.5); println!(" ... ok"); print!("Testing Antenna::get_distance_with_W()"); assert!(f64::abs(5.0 - a.get_distance_with_W(3.98e-9)) < 0.5); assert!(f64::abs(10.0 - a.get_distance_with_W(9.91e-10)) < 0.5); assert!(f64::abs(20.0 - a.get_distance_with_W(2.48e-10)) < 0.5); println!(" ... ok"); }