kinda stuck at this point so making a commit
This commit is contained in:
@@ -4,8 +4,8 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
avam-protocol = { path = "../avam-protocol" }
|
||||
anyhow = { version = "1.0" }
|
||||
avam-protocol = { path = "../avam-protocol" }
|
||||
base64 = { version = "0.22.1", default-features = false }
|
||||
clap = { version = "4.5.20", features = ["derive"] }
|
||||
config = "0.14.0"
|
||||
@@ -28,6 +28,9 @@ reqwest = { version = "0.12.8", default-features = false, features = [
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_qs = "0.13.0"
|
||||
sha256 = "1.5.0"
|
||||
simconnect-sdk = { path = "D:/source/MSFS/simconnect-sdk-rs/simconnect-sdk", features = [
|
||||
"derive",
|
||||
] }
|
||||
tauri-winrt-notification = "0.6.0"
|
||||
thiserror = { version = "1.0" }
|
||||
time = "0.3.36"
|
||||
@@ -37,7 +40,7 @@ tokio-tungstenite = { version = "0.24.0", features = [
|
||||
] }
|
||||
toml = "0.8"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["time"] }
|
||||
tracing-subscriber = { version = "0.3.18", features = ["time", "fmt", "std"] }
|
||||
tray-icon = "0.19"
|
||||
uuid = { version = "1.10.0", features = ["fast-rng", "serde", "v4"] }
|
||||
winit = "0.30"
|
||||
|
@@ -1,5 +1,27 @@
|
||||
use windres::Build;
|
||||
|
||||
fn main() {
|
||||
Build::new().compile("icon.rc").unwrap();
|
||||
fn main() -> std::io::Result<()> {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
let target_os = std::env::var("CARGO_CFG_TARGET_OS");
|
||||
if target_os.as_deref() == Ok("windows") {
|
||||
let name = "Avii's Virtual Airline Manager";
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let mut sv = version.split('.').collect::<Vec<_>>();
|
||||
while sv.len() < 4 {
|
||||
sv.push("0");
|
||||
}
|
||||
let file_version = format!("{}, {}, {}, {}", sv[0], sv[1], sv[2], sv[3]);
|
||||
windres::Build::new()
|
||||
.define(
|
||||
"THE_FILE",
|
||||
Some(format!(r#""{name} Client Module""#).as_str()),
|
||||
)
|
||||
.define("THE_PROJECT", Some(format!(r#""{name}""#).as_str()))
|
||||
.define("THE_VERSION", Some(format!(r#""{version}""#).as_str()))
|
||||
.define("THE_FILEVERSION", Some(file_version.as_str()))
|
||||
.compile("res/resource.rc")?;
|
||||
for entry in std::fs::read_dir("res")? {
|
||||
let entry = entry?;
|
||||
println!("cargo:rerun-if-changed={}", entry.path().display());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -1 +0,0 @@
|
||||
1 ICON "icon.ico"
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
28
avam-client/res/resource.rc
Normal file
28
avam-client/res/resource.rc
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma code_page(65001)
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION THE_FILEVERSION
|
||||
PRODUCTVERSION THE_FILEVERSION
|
||||
FILEFLAGSMASK 0x0000003Fl //VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0x0
|
||||
FILEOS 0x00040004l //VOS_NT_WINDOWS32
|
||||
FILETYPE 0x00000001l //VFT_APP
|
||||
FILESUBTYPE 0x00000000l //VFT2_UNKNOWN
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904B0"
|
||||
{
|
||||
VALUE "FileDescription", THE_FILE
|
||||
VALUE "FileVersion", THE_VERSION
|
||||
VALUE "ProductVersion", THE_VERSION
|
||||
VALUE "ProductName", THE_PROJECT
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo"
|
||||
{
|
||||
VALUE "Translation", 0x409, 0x4B0
|
||||
}
|
||||
}
|
||||
|
||||
1 ICON "res/icon.ico"
|
@@ -86,7 +86,7 @@ pub async fn start(
|
||||
Message::Binary(encoded_message)
|
||||
}
|
||||
d => {
|
||||
tracing::info!("sending packet: {:?}", &d);
|
||||
// tracing::info!("sending packet: {:#?}", &d);
|
||||
let Ok(encoded_message) = d.encode() else {
|
||||
tracing::error!(
|
||||
"Unable to encode message for sending: {:#?}",
|
||||
|
@@ -262,13 +262,15 @@ fn init_logging() -> Result<(), anyhow::Error> {
|
||||
#[cfg(not(debug_assertions))]
|
||||
let file = File::options().append(true).open(&log_file)?;
|
||||
|
||||
let fmt = tracing_subscriber::fmt::layer().with_filter(tracing_subscriber::filter::filter_fn(
|
||||
|metadata| metadata.level() < &Level::TRACE,
|
||||
));
|
||||
let fmt = tracing_subscriber::fmt::layer();
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
let fmt = fmt.with_ansi(false).with_writer(Arc::new(file));
|
||||
|
||||
let fmt = fmt.with_filter(tracing_subscriber::filter::filter_fn(|metadata| {
|
||||
metadata.level() < &Level::TRACE
|
||||
}));
|
||||
|
||||
tracing_subscriber::registry().with(fmt).init();
|
||||
|
||||
Ok(())
|
||||
|
@@ -194,34 +194,6 @@ impl AuthorizeRequest {
|
||||
scope,
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn client_id(&self) -> uuid::Uuid {
|
||||
// self.client_id
|
||||
// }
|
||||
|
||||
// pub fn response_type(&self) -> ResponseType {
|
||||
// self.response_type.clone()
|
||||
// }
|
||||
|
||||
// pub fn state(&self) -> Option<String> {
|
||||
// self.state.clone()
|
||||
// }
|
||||
|
||||
// pub fn code_challenge(&self) -> String {
|
||||
// self.code_challenge.clone()
|
||||
// }
|
||||
|
||||
// pub fn code_challenge_method(&self) -> Option<CodeChallengeMethod> {
|
||||
// self.code_challenge_method.clone()
|
||||
// }
|
||||
|
||||
// pub fn redirect_uri(&self) -> String {
|
||||
// self.redirect_uri.clone()
|
||||
// }
|
||||
|
||||
// pub fn scope(&self) -> Option<String> {
|
||||
// self.scope.clone()
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
|
@@ -1,18 +1,210 @@
|
||||
use std::time::Duration;
|
||||
mod models;
|
||||
|
||||
use avam_protocol::SimConnectPacket;
|
||||
use core::ops::ControlFlow;
|
||||
use models::*;
|
||||
use simconnect_sdk::{Notification, Object, SimConnect as SC, SystemEvent, SystemEventRequest};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::{
|
||||
sync::broadcast::{Receiver, Sender},
|
||||
sync::{
|
||||
broadcast::{Receiver, Sender},
|
||||
RwLock,
|
||||
},
|
||||
time::sleep,
|
||||
};
|
||||
|
||||
use crate::state_machine::Event;
|
||||
|
||||
pub struct SimState {
|
||||
atc_id: String,
|
||||
// gps location
|
||||
// fuel state
|
||||
// cargo state
|
||||
// is landed
|
||||
// is stopped
|
||||
// etc
|
||||
// basically, all the data we wanna send to socket
|
||||
|
||||
// we also need to know if we're in a flight here, and what flight,
|
||||
// mission parameters etc maybe
|
||||
// unless we just wanna keep that purely serverside..
|
||||
// and only process incoming packets if there is an activem mission.
|
||||
|
||||
// the thing i _dont_ want, is to be invasive with alerts and notifications
|
||||
// that the user is "forgetting" to start a flight etc with AVAM running
|
||||
// basically, avam should be able to be running always without the user noticing
|
||||
// any interaction is done via the dashboard
|
||||
// starting, stopping, status etc
|
||||
|
||||
// eventually even with "realistic" flightplans, from time of takeoff, estimate time of arrival,
|
||||
// and even have time-critical jobs that need to get finished before a set time
|
||||
}
|
||||
|
||||
impl Default for SimState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
atc_id: String::from("AVAM"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SimConnect {
|
||||
simconnect_receiver: Receiver<SimConnectPacket>, // Data from the socket
|
||||
socket_sender: Sender<SimConnectPacket>, // Data to the socket
|
||||
sender: Sender<Event>,
|
||||
receiver: Receiver<Event>,
|
||||
state: Arc<RwLock<SimState>>,
|
||||
}
|
||||
|
||||
impl SimConnect {
|
||||
async fn open(&self, client: &mut SC) -> Result<(), anyhow::Error> {
|
||||
client.subscribe_to_system_event(SystemEventRequest::AircraftLoaded)?;
|
||||
client.subscribe_to_system_event(SystemEventRequest::SimStart)?;
|
||||
|
||||
let id = client.register_object::<AtcID>()?;
|
||||
client.register_object::<Airplane>()?;
|
||||
client.register_object::<Fuel>()?;
|
||||
client.register_object::<Gps>()?;
|
||||
client.register_object::<OnGround>()?;
|
||||
client.register_object::<IsParked>()?;
|
||||
|
||||
let value = self.state.read().await.atc_id.clone();
|
||||
tracing::info!("Updating ATC_ID: {}", &value);
|
||||
client.set_data_on_sim_object_with_id(id, &mut atc_id(&value)?)?;
|
||||
|
||||
let _ = self.sender.send(Event::SimConnected);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn object(&self, _: &mut SC, object: &Object) -> Result<(), anyhow::Error> {
|
||||
if let Ok(data) = Airplane::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::Airplane(avam_protocol::Airplane {
|
||||
atc_type: data.atc_type,
|
||||
atc_model: data.atc_model,
|
||||
title: data.title,
|
||||
category: data.category,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok(data) = Fuel::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::Fuel(avam_protocol::Fuel {
|
||||
weight: data.weight,
|
||||
center_quantity: data.center_quantity,
|
||||
center_capacity: data.center_capacity,
|
||||
center2_quantity: data.center2_quantity,
|
||||
center2_capacity: data.center2_capacity,
|
||||
center3_quantity: data.center3_quantity,
|
||||
center3_capacity: data.center3_capacity,
|
||||
left_main_quantity: data.left_main_quantity,
|
||||
left_main_capacity: data.left_main_capacity,
|
||||
left_aux_quantity: data.left_aux_quantity,
|
||||
left_aux_capacity: data.left_aux_capacity,
|
||||
left_tip_quantity: data.left_tip_quantity,
|
||||
left_tip_capacity: data.left_tip_capacity,
|
||||
right_main_quantity: data.right_main_quantity,
|
||||
right_main_capacity: data.right_main_capacity,
|
||||
right_aux_quantity: data.right_aux_quantity,
|
||||
right_aux_capacity: data.right_aux_capacity,
|
||||
right_tip_quantity: data.right_tip_quantity,
|
||||
right_tip_capacity: data.right_tip_capacity,
|
||||
external1_quantity: data.external1_quantity,
|
||||
external1_capacity: data.external1_capacity,
|
||||
external2_quantity: data.external2_quantity,
|
||||
external2_capacity: data.external2_capacity,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok(data) = Gps::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::Gps(avam_protocol::Gps {
|
||||
lat: data.lat,
|
||||
lon: data.lon,
|
||||
alt: data.alt,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok(data) = OnGround::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::OnGround(avam_protocol::OnGround {
|
||||
sim_on_ground: data.sim_on_ground,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Change to parking break state or something, unless we're a helicopter, then we dont have one
|
||||
if let Ok(data) = IsParked::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::IsParked(avam_protocol::IsParked {
|
||||
is_parked: data.is_parked,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn system_event(
|
||||
&self,
|
||||
client: &mut SC,
|
||||
event: &SystemEvent,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
match event {
|
||||
SystemEvent::AircraftLoaded { .. } => {
|
||||
tracing::info!("Aircraft Loaded!");
|
||||
let id = client.get_object_id::<AtcID>()?;
|
||||
|
||||
let value = self.state.read().await.atc_id.clone();
|
||||
tracing::info!("Updating ATC_ID: {}", &value);
|
||||
for _ in 1..=10 {
|
||||
client.set_data_on_sim_object_with_id(id, &mut atc_id(&value)?)?;
|
||||
sleep(Duration::from_millis(50)).await;
|
||||
}
|
||||
}
|
||||
SystemEvent::SimStart => {
|
||||
tracing::info!("Sim Start");
|
||||
}
|
||||
|
||||
// SystemEvent::OneSecond => todo!(),
|
||||
// SystemEvent::FourSeconds => todo!(),
|
||||
// SystemEvent::SixTimesPerSecond => todo!(),
|
||||
// SystemEvent::AircraftLoaded { file_name } => todo!(),
|
||||
// SystemEvent::Crashed => todo!(),
|
||||
// SystemEvent::CrashReset => todo!(),
|
||||
// SystemEvent::FlightSaved { file_name } => todo!(),
|
||||
// SystemEvent::FlightPlanActivated { file_name } => todo!(),
|
||||
// SystemEvent::FlightPlanDeactivated => todo!(),
|
||||
// SystemEvent::Frame {
|
||||
// frame_rate,
|
||||
// sim_speed,
|
||||
// } => todo!(),
|
||||
// SystemEvent::Pause { state } => todo!(),
|
||||
// SystemEvent::Paused => todo!(),
|
||||
// SystemEvent::PauseFrame {
|
||||
// frame_rate,
|
||||
// sim_speed,
|
||||
// } => todo!(),
|
||||
// SystemEvent::PositionChanged => todo!(),
|
||||
// SystemEvent::Sim { state } => todo!(),
|
||||
// SystemEvent::SimStart => todo!(),
|
||||
// SystemEvent::SimStop => todo!(),
|
||||
// SystemEvent::Sound { state } => todo!(),
|
||||
// SystemEvent::Unpaused => todo!(),
|
||||
// SystemEvent::View { view } => todo!(),
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl SimConnect {
|
||||
@@ -27,23 +219,83 @@ impl SimConnect {
|
||||
socket_sender,
|
||||
sender,
|
||||
receiver,
|
||||
state: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&self) -> Result<(), anyhow::Error> {
|
||||
let mut receiver = self.receiver.resubscribe();
|
||||
let mut simconnect_receiver = self.simconnect_receiver.resubscribe();
|
||||
let state = self.state.clone();
|
||||
let mut sc: Option<SC> = None;
|
||||
loop {
|
||||
if let Ok(Event::Quit) = receiver.try_recv() {
|
||||
break;
|
||||
}
|
||||
|
||||
// handle simconnect stuff here
|
||||
if let Ok(packet) = simconnect_receiver.try_recv() {
|
||||
match packet {
|
||||
SimConnectPacket::AtcID(value) => {
|
||||
state.write().await.atc_id = value.clone();
|
||||
if let Some(client) = sc.as_mut() {
|
||||
if let Ok(id) = client.get_object_id::<AtcID>() {
|
||||
tracing::info!("Updating ATC_ID: {}", &value);
|
||||
client.set_data_on_sim_object_with_id(id, &mut atc_id(&value)?)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
SimConnectPacket::Fuel(_) => unreachable!(), // Outgoing packet, not handled here (yet) we probably need to set fuel state somehow
|
||||
SimConnectPacket::Airplane(_) => unreachable!(),
|
||||
SimConnectPacket::Gps(_) => unreachable!(), // Outgoing packet, not handled here (yet) we probably need to set position somehow
|
||||
SimConnectPacket::OnGround(_) => unreachable!(), // Outgoing packet, not handled here
|
||||
SimConnectPacket::IsParked(_) => unreachable!(), // Outgoing packet, not handled here
|
||||
}
|
||||
}
|
||||
|
||||
if sc.is_none() {
|
||||
if let Ok(simconnect) = SC::new("Avii's Virtual Airline Manager") {
|
||||
sc = Some(simconnect);
|
||||
tracing::info!("Connected");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(client) = sc.as_mut() {
|
||||
if self.handle(client).await.is_break() {
|
||||
tracing::info!("Disconnected");
|
||||
sc = None;
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle(&self, client: &mut SC) -> ControlFlow<(), ()> {
|
||||
if let Ok(Some(event)) = client.get_next_dispatch() {
|
||||
if let Err(e) = match event {
|
||||
Notification::Open => self.open(client).await,
|
||||
Notification::Object(ref object) => self.object(client, object).await,
|
||||
Notification::SystemEvent(ref system_event) => {
|
||||
self.system_event(client, system_event).await
|
||||
}
|
||||
// Notification::ClientEvent(ref client_event) => todo!(),
|
||||
// Notification::AirportList(ref vec) => todo!(),
|
||||
// Notification::WaypointList(ref vec) => todo!(),
|
||||
// Notification::NdbList(ref vec) => todo!(),
|
||||
// Notification::VorList(ref vec) => todo!(),
|
||||
Notification::Quit => {
|
||||
let _ = self.sender.send(Event::SimDisconnected);
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
_ => todo!(),
|
||||
} {
|
||||
tracing::error!("Error handling SimConnect::Notification: {:#?}", e);
|
||||
};
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn start(
|
||||
|
123
avam-client/src/simconnect/models.rs
Normal file
123
avam-client/src/simconnect/models.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use simconnect_sdk::SimConnectObject;
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct AtcID {
|
||||
#[simconnect(name = "ATC ID")]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
pub(super) fn atc_id(value: &str) -> Result<AtcIDCPacked, anyhow::Error> {
|
||||
if value.len() > 10 {
|
||||
return Err(anyhow::anyhow!("ATC_ID exceeding 10 characters"));
|
||||
}
|
||||
let cs = CString::new(value.to_uppercase())?;
|
||||
let mut buffer = [0i8; 256];
|
||||
for (i, b) in cs.to_bytes_with_nul().iter().enumerate() {
|
||||
buffer[i] = *b as i8;
|
||||
}
|
||||
Ok(AtcIDCPacked { value: buffer })
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct Airplane {
|
||||
#[simconnect(name = "ATC TYPE")]
|
||||
pub atc_type: String,
|
||||
#[simconnect(name = "ATC MODEL")]
|
||||
pub atc_model: String,
|
||||
#[simconnect(name = "TITLE")]
|
||||
pub title: String,
|
||||
#[simconnect(name = "CATEGORY")]
|
||||
pub category: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct Fuel {
|
||||
#[simconnect(name = "FUEL TANK CENTER QUANTITY", unit = "gallons")]
|
||||
pub center_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK CENTER CAPACITY", unit = "gallons")]
|
||||
pub center_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK CENTER2 QUANTITY", unit = "gallons")]
|
||||
pub center2_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK CENTER2 CAPACITY", unit = "gallons")]
|
||||
pub center2_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK CENTER3 QUANTITY", unit = "gallons")]
|
||||
pub center3_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK CENTER3 CAPACITY", unit = "gallons")]
|
||||
pub center3_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK LEFT MAIN QUANTITY", unit = "gallons")]
|
||||
pub left_main_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK LEFT MAIN CAPACITY", unit = "gallons")]
|
||||
pub left_main_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK LEFT AUX QUANTITY", unit = "gallons")]
|
||||
pub left_aux_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK LEFT AUX CAPACITY", unit = "gallons")]
|
||||
pub left_aux_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK LEFT TIP QUANTITY", unit = "gallons")]
|
||||
pub left_tip_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK LEFT TIP CAPACITY", unit = "gallons")]
|
||||
pub left_tip_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK RIGHT MAIN QUANTITY", unit = "gallons")]
|
||||
pub right_main_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK RIGHT MAIN CAPACITY", unit = "gallons")]
|
||||
pub right_main_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK RIGHT AUX QUANTITY", unit = "gallons")]
|
||||
pub right_aux_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK RIGHT AUX CAPACITY", unit = "gallons")]
|
||||
pub right_aux_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK RIGHT TIP QUANTITY", unit = "gallons")]
|
||||
pub right_tip_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK RIGHT TIP CAPACITY", unit = "gallons")]
|
||||
pub right_tip_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL1 QUANTITY", unit = "gallons")]
|
||||
pub external1_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL1 CAPACITY", unit = "gallons")]
|
||||
pub external1_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL2 QUANTITY", unit = "gallons")]
|
||||
pub external2_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL2 CAPACITY", unit = "gallons")]
|
||||
pub external2_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL WEIGHT PER GALLON", unit = "pounds")]
|
||||
pub weight: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct Gps {
|
||||
#[simconnect(name = "PLANE LATITUDE", unit = "degrees")]
|
||||
pub lat: f64,
|
||||
#[simconnect(name = "PLANE LONGITUDE", unit = "degrees")]
|
||||
pub lon: f64,
|
||||
#[simconnect(name = "PLANE ALTITUDE", unit = "feet")]
|
||||
pub alt: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct OnGround {
|
||||
#[simconnect(name = "SIM ON GROUND")]
|
||||
pub sim_on_ground: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct IsParked {
|
||||
#[simconnect(name = "PLANE IN PARKING STATE")]
|
||||
pub is_parked: bool,
|
||||
}
|
Reference in New Issue
Block a user