lib.rs (4806B)
1 #[deny(unused_imports)] 2 #[deny(missing_docs)] 3 use influxdb_client::{Client, Point, Precision, TimestampOptions}; 4 use std::{ 5 sync::Arc, 6 time::{Duration, Instant, SystemTime, UNIX_EPOCH}, 7 }; 8 use tokio::runtime::{self, Runtime}; 9 use xplm::{ 10 debug, 11 flight_loop::{FlightLoop, FlightLoopCallback}, 12 plugin::{Plugin, PluginInfo}, 13 xplane_plugin, 14 }; 15 16 use crate::location::Location; 17 use crate::{energy::Energy, error::Error}; 18 19 mod energy; 20 mod error; 21 mod location; 22 23 struct DataMonitorPlugin { 24 loophandler: LoopHandler, 25 flightloop: Option<FlightLoop>, 26 } 27 28 #[derive(Clone)] 29 struct LoopHandler { 30 location: Location, 31 energy: Energy, 32 last_run: Instant, 33 start_time: SystemTime, 34 leg_started: bool, 35 influx: Arc<influxdb_client::Client>, 36 rt: Arc<Runtime>, 37 } 38 39 impl FlightLoopCallback for LoopHandler { 40 fn flight_loop(&mut self, state: &mut xplm::flight_loop::LoopState) { 41 let battery_on = self.energy.battery_on(); 42 let gpu_on = self.energy.gpu_on(); 43 let apu_on = self.energy.apu_on(); 44 if (battery_on || gpu_on || apu_on) && !self.leg_started { 45 // TODO reset on FP change 46 self.leg_started = true; 47 } 48 if self.last_run.elapsed() >= Duration::from_secs(1) && self.leg_started { 49 let latitude = self.location.lat(); 50 let longitude = self.location.lon(); 51 let altitude = self.location.alt(); 52 let timestamp = self 53 .start_time 54 .duration_since(UNIX_EPOCH) 55 .expect("Time went backwards") 56 .as_secs() as i64; 57 58 let client = self.influx.clone(); 59 self.rt.spawn(async move { 60 let location_point = Point::new("location") 61 .tag("start_time", timestamp) 62 .field("latitude", latitude) 63 .field("longitude", longitude) 64 .field("altitude_feet", altitude); 65 let status_point = Point::new("status") 66 .tag("start_time", timestamp) 67 .field("battery_on", battery_on) 68 .field("gpu_on", gpu_on) 69 .field("apu_on", apu_on); 70 let points = vec![&location_point, &status_point]; 71 if let Err(e) = client.insert_points(points, TimestampOptions::None).await { 72 debug(format!("[DATAMONITOR][ERROR] Sending Points: {:#?}\n", e)); 73 }; 74 }); 75 self.last_run = Instant::now(); 76 } 77 state.call_next_loop() 78 } 79 } 80 81 impl DataMonitorPlugin { 82 pub(crate) fn start(&mut self) { 83 debug("[DATAMONITOR] starting\n"); 84 let mut flight_loop = FlightLoop::new(self.loophandler.clone()); 85 flight_loop.schedule_immediate(); 86 self.flightloop = Some(flight_loop); 87 debug("[DATAMONITOR] started\n"); 88 } 89 } 90 91 impl Plugin for DataMonitorPlugin { 92 type Error = Error; 93 94 fn start() -> Result<Self, Self::Error> { 95 let location = Location::new(); 96 if let Err(ref e) = location { 97 debug(format!("[DATAMONITOR][ERROR] Location init: {:?}\n", e)); 98 } 99 let energy = Energy::new(); 100 if let Err(ref e) = energy { 101 debug(format!("[DATAMONITOR][ERROR] Energy init: {:?}\n", e)); 102 } 103 104 let influx_client = Client::new("http://10.0.0.1:8086", 105 "wuL5_5sg_zlaQdkDWhmiFZ9r-Fx1rWgNR407czXOeQmYU1PHlp0nwpmjjW270PzEgEctx0AqD_K7K-h9Ein6Pg==") 106 .with_org("Nordgedanken") 107 .with_bucket("flightdata") 108 .with_precision(Precision::MS); 109 110 let rt = runtime::Runtime::new(); 111 if let Err(ref e) = rt { 112 debug(format!("[DATAMONITOR][ERROR] Creating runtime: {:#?}\n", e)); 113 } 114 115 let loophandler = LoopHandler { 116 location: location.unwrap(), 117 energy: energy.unwrap(), 118 last_run: Instant::now(), 119 influx: Arc::new(influx_client), 120 start_time: SystemTime::now(), 121 leg_started: false, 122 rt: Arc::new(rt.unwrap()), 123 }; 124 let plugin = DataMonitorPlugin { 125 loophandler, 126 flightloop: None, 127 }; 128 Ok(plugin) 129 } 130 fn enable(&mut self) -> Result<(), Self::Error> { 131 self.start(); 132 Ok(()) 133 } 134 fn disable(&mut self) { 135 debug("[DATAMONITOR][INFO] Stopping threads\n"); 136 } 137 138 fn info(&self) -> xplm::plugin::PluginInfo { 139 PluginInfo { 140 name: String::from("Datamonitor"), 141 signature: String::from("dev.nordgedanken.datamonitor"), 142 description: String::from( 143 "Gets certain datarefs to display in a grafana for review of flights.", 144 ), 145 } 146 } 147 } 148 149 xplane_plugin!(DataMonitorPlugin);