diff --git a/Cargo.lock b/Cargo.lock index f37d4f5..7cc05a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anyhow" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" + [[package]] name = "autocfg" version = "1.1.0" @@ -23,7 +29,7 @@ version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cexpr", "clang-sys", "lazy_static", @@ -46,6 +52,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + [[package]] name = "cexpr" version = "0.6.0" @@ -61,6 +73,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clang-sys" version = "1.6.1" @@ -72,6 +90,16 @@ dependencies = [ "libloading", ] +[[package]] +name = "ctrlc" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +dependencies = [ + "nix", + "windows-sys", +] + [[package]] name = "dissimilar" version = "1.0.6" @@ -126,9 +154,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.142" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libloading" @@ -170,6 +198,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -257,9 +297,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -427,6 +467,17 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "testapp" +version = "0.1.0" +dependencies = [ + "anyhow", + "ctrlc", + "simconnect-sdk", + "tracing", + "tracing-subscriber", +] + [[package]] name = "thiserror" version = "1.0.40" @@ -476,11 +527,10 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -488,9 +538,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -499,9 +549,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -509,20 +559,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -606,6 +656,79 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "winnow" version = "0.4.4" diff --git a/Cargo.toml b/Cargo.toml index bb9f3a4..e9e1b2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,5 @@ [workspace] -members = [ - "examples", - "simconnect-sdk", - "simconnect-sdk-derive", -] +resolver = "2" +members = ["examples", "simconnect-sdk", "simconnect-sdk-derive", "testapp"] + +default-members = ["testapp"] diff --git a/simconnect-sdk/build.rs b/simconnect-sdk/build.rs index 5aea7d5..2ec3836 100644 --- a/simconnect-sdk/build.rs +++ b/simconnect-sdk/build.rs @@ -32,6 +32,7 @@ fn main() { .allowlist_function("SimConnect_Open") .allowlist_function("SimConnect_RemoveClientEvent") .allowlist_function("SimConnect_RequestDataOnSimObject") + .allowlist_function("SimConnect_SetDataOnSimObject") .allowlist_function("SimConnect_RequestFacilitiesList") .allowlist_function("SimConnect_SetNotificationGroupPriority") .allowlist_function("SimConnect_SubscribeToFacilities") diff --git a/simconnect-sdk/src/simconnect/objects.rs b/simconnect-sdk/src/simconnect/objects.rs index 92b77d6..752a234 100644 --- a/simconnect-sdk/src/simconnect/objects.rs +++ b/simconnect-sdk/src/simconnect/objects.rs @@ -109,4 +109,47 @@ impl SimConnect { ) }) } + + pub fn set_data_on_sim_object(&self, obj: &mut T) -> Result<(), SimConnectError> { + let type_name: String = std::any::type_name::().into(); + + let request_id = self + .registered_objects + .get(&type_name) + .ok_or_else(|| SimConnectError::ObjectNotRegistered(type_name.clone()))?; + + success!(unsafe { + bindings::SimConnect_SetDataOnSimObject( + self.handle.as_ptr(), + request_id.id, + bindings::SIMCONNECT_OBJECT_ID_USER, + Condition::None.into(), + 0, + size_of::().try_into().unwrap(), + obj as *mut _ as *mut std::ffi::c_void, + ) + }) + } + + pub fn set_data_on_sim_object_with_id( + &self, + request_id: u32, + obj: &mut T, + ) -> Result<(), SimConnectError> { + // Strings require to be something specific, so until we can figure out how to + // convert the strings "on-the-fly" + // we'll use the packed variant of the struct, but it'll need a custom request_id + + success!(unsafe { + bindings::SimConnect_SetDataOnSimObject( + self.handle.as_ptr(), + request_id, + bindings::SIMCONNECT_OBJECT_ID_USER, + Condition::None.into(), + 0, + size_of::().try_into().unwrap(), + obj as *mut _ as *mut std::ffi::c_void, + ) + }) + } } diff --git a/testapp/Cargo.toml b/testapp/Cargo.toml new file mode 100644 index 0000000..d32833d --- /dev/null +++ b/testapp/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "testapp" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.90" +ctrlc = "3.4.5" +# simconnect-rs = { path = "../simconnect-rs" } +simconnect-sdk = { path = "../simconnect-sdk", features = ["derive"] } +tracing = "0.1.40" +tracing-subscriber = "0.3.18" diff --git a/testapp/src/ctrl_c.rs b/testapp/src/ctrl_c.rs new file mode 100644 index 0000000..96fe6a9 --- /dev/null +++ b/testapp/src/ctrl_c.rs @@ -0,0 +1,28 @@ +use std::sync::{ + atomic::{AtomicU8, Ordering}, + Arc, +}; + +pub struct CtrlC { + counter: Arc, +} + +impl CtrlC { + pub fn new() -> Self { + let counter: Arc = Default::default(); + let c = counter.clone(); + ctrlc::set_handler(move || { + c.fetch_add(1, Ordering::SeqCst); + if c.load(Ordering::SeqCst) >= 3 { + std::process::exit(1); + } + }) + .unwrap(); + + Self { counter } + } + + pub fn count(&self) -> u8 { + self.counter.load(Ordering::SeqCst) + } +} diff --git a/testapp/src/main.rs b/testapp/src/main.rs new file mode 100644 index 0000000..b1c884e --- /dev/null +++ b/testapp/src/main.rs @@ -0,0 +1,159 @@ +mod ctrl_c; + +use std::{ + borrow::Cow, + ffi::{CStr, CString}, + thread::sleep, + time::Duration, +}; + +use ctrl_c::CtrlC; +// use simconnect_rs::SimConnect; +use simconnect_sdk::{Notification, SimConnect, SimConnectObject, SystemEventRequest}; + +#[derive(Debug, Clone, SimConnectObject)] +#[simconnect(period = "second")] +struct AtcID { + #[simconnect(name = "ATC ID")] + value: String, +} + +// #[derive(Debug, Clone, SimConnectObject)] +// #[simconnect(period = "second")] +// #[allow(dead_code)] +// struct AirplaneData { +// #[simconnect(name = "TITLE")] +// title: String, +// #[simconnect(name = "ATC ID")] +// atc_id: String, +// #[simconnect(name = "CATEGORY")] +// category: String, +// #[simconnect(name = "PLANE LATITUDE", unit = "degrees")] +// lat: f64, +// #[simconnect(name = "PLANE LONGITUDE", unit = "degrees")] +// lon: f64, +// #[simconnect(name = "PLANE ALTITUDE", unit = "feet")] +// alt: f64, +// #[simconnect(name = "SIM ON GROUND")] +// sim_on_ground: bool, +// } + +#[derive(Debug, Clone, SimConnectObject)] +#[simconnect(period = "second")] +struct Fuel { + #[simconnect(name = "FUEL TANK CENTER QUANTITY", unit = "gallons")] + ft1: f64, + #[simconnect(name = "FUEL TANK LEFT MAIN QUANTITY", unit = "gallons")] + wt1: f64, + #[simconnect(name = "FUEL TANK RIGHT MAIN QUANTITY", unit = "gallons")] + wt2: f64, + #[simconnect(name = "FUEL TANK EXTERNAL1 QUANTITY", unit = "gallons")] + et1: f64, + #[simconnect(name = "FUEL TANK EXTERNAL2 QUANTITY", unit = "gallons")] + et2: f64, + #[simconnect(name = "FUEL TANK CENTER3 QUANTITY", unit = "gallons")] + et3: f64, + #[simconnect(name = "FUEL TANK CENTER2 QUANTITY", unit = "gallons")] + ft2: f64, +} + +fn main() -> Result<(), anyhow::Error> { + use tracing::Level; + use tracing_subscriber::layer::SubscriberExt; + use tracing_subscriber::util::SubscriberInitExt; + use tracing_subscriber::Layer; + + let fmt = tracing_subscriber::fmt::layer().with_filter(tracing_subscriber::filter::filter_fn( + |metadata| metadata.level() < &Level::TRACE, + )); + + tracing_subscriber::registry().with(fmt).init(); + + let Ok(mut simconnect) = SimConnect::new("Avii's Virtual Airline Manager") else { + panic!("Game not running, gotta wait for it here"); + }; + + // .subscribe(SomeEvent); + + let mut id = 0; + + let ctrl_c = CtrlC::new(); + + loop { + if let Ok(Some(event)) = simconnect.get_next_dispatch() { + match event { + Notification::Open => { + simconnect.subscribe_to_system_event(SystemEventRequest::FlightLoaded)?; + + id = simconnect.register_object::()?; + simconnect.register_object::()?; + + let cs = CString::new("FAST")?; + let mut buffer = [0i8; 256]; + for (i, b) in cs.to_bytes_with_nul().iter().enumerate() { + buffer[i] = *b as i8; + } + + simconnect + .set_data_on_sim_object_with_id(id, &mut AtcIDCPacked { value: buffer })?; + tracing::info!("ATC_ID set"); + + simconnect.set_data_on_sim_object(&mut Fuel { + ft1: 0.0, + wt1: 20.0, + wt2: 20.0, + et1: 0.0, + et2: 0.0, + et3: 0.0, + ft2: 0.0, + })?; + tracing::info!("FUEL set"); + } + Notification::Object(object) => { + // if let Ok(fuel) = Fuel::try_from(&object) { + // // dbg!(fuel); + // continue; + // } + } + Notification::SystemEvent(system_event) => { + if let simconnect_sdk::SystemEvent::FlightLoaded { .. } = system_event { + let cs = CString::new("RAWR")?; + let mut buffer = [0i8; 256]; + for (i, b) in cs.to_bytes_with_nul().iter().enumerate() { + buffer[i] = *b as i8; + } + + simconnect.set_data_on_sim_object_with_id( + id, + &mut AtcIDCPacked { value: buffer }, + )?; + tracing::info!("ATC_ID set"); + + simconnect.set_data_on_sim_object(&mut Fuel { + ft1: 0.0, + wt1: 20.0, + wt2: 20.0, + et1: 0.0, + et2: 0.0, + et3: 0.0, + ft2: 0.0, + })?; + tracing::info!("FUEL set"); + } + } + Notification::Quit => panic!("Sim Quit"), + _ => todo!(), + } + } + + sleep(Duration::from_millis(1000)); + + if ctrl_c.count() > 0 { + break; + } + } + + drop(simconnect); + + Ok(()) +}