use chrono::{DateTime, Utc}; use influxdb::{InfluxDbWriteable, ReadQuery}; use serde::{Deserialize, Serialize}; use crate::helper::for_async::get_influx_cli; use crate::models::BEACONMEASURE_TIME_WINDOW; use crate::MAC; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize, InfluxDbWriteable)] pub struct BeaconMeasure { #[influxdb(tag)] pub beacon_id: MAC, pub rssi: f64, pub time: DateTime, } #[derive(Serialize, Deserialize)] struct Tags { beacon_id: MAC, } impl BeaconMeasure { #[allow(non_snake_case)] pub fn new(beacon_id: &MAC, rssi_W: f64) -> BeaconMeasure { BeaconMeasure { beacon_id: *beacon_id, rssi: rssi_W, time: chrono::Utc::now(), } } pub async fn write_for(self, device_id: &str) -> Result { let table_name = format!("measure_{}", device_id); get_influx_cli() .query(self.into_query(table_name.as_str())) .await } pub async fn get_for(device_id: &str) -> Result, influxdb::Error> { let query = format!( "SELECT mean(rssi) FROM /measure_{}/ WHERE time > now() - {}s AND time < now() GROUP BY beacon_id;", device_id, BEACONMEASURE_TIME_WINDOW); let mut database_result = get_influx_cli().json_query(ReadQuery::new(query)).await?; #[derive(Deserialize)] struct Value { time: DateTime, mean: f64, } let vect = database_result .deserialize_next_tagged::()? .series .into_iter() .map(|measure| BeaconMeasure { beacon_id: measure.tags.beacon_id, rssi: measure.values[0].mean, time: measure.values[0].time, }) .collect::>(); Ok(vect) } } #[tokio::test] async fn beacon_measure_test() { print!("Testing BeaconMeasure::* read/write methods"); let bm1 = BeaconMeasure::new(&MAC::new("AB:CD:EF:12:34:56"), 0.0); let bm = bm1.clone(); let _result = bm.write_for("AB:CD:EF:12:34:56").await; let bm2 = BeaconMeasure::get_for("AB:CD:EF:12:34:56").await.unwrap(); assert_eq!(bm2.len(), 1); assert_eq!(bm1.beacon_id, bm2[0].beacon_id); assert_eq!(bm1.rssi, bm2[0].rssi); //wait for the time window to pass let delay = BEACONMEASURE_TIME_WINDOW * 1000 + 500; tokio::time::sleep(tokio::time::Duration::from_millis(delay)).await; let bm2 = BeaconMeasure::get_for("AB:CD:EF:12:34:56").await.unwrap(); assert_eq!(bm2.len(), 0); println!(" ... ok"); }