diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ea9c13..37e28d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: toolchain: stable override: true - uses: davidB/rust-cargo-make@v1 - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Run format run: cargo make format - name: Run check diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..4fa2da4 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,27 @@ +name: Crates.io +on: + release: + types: + - created +jobs: + publish: + name: Publish + runs-on: windows-2022 + steps: + - uses: actions/checkout@v3 + with: + ref: main + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Run build + run: cargo build --release --verbose + - name: Run publish simconnect-sdk-derive + run: cargo publish -p simconnect-sdk-derive --token ${{ secrets.CRATES_IO_TOKEN }} + - name: Sleep for 30 seconds + run: Start-Sleep -s 30 + shell: powershell + - name: Run publish simconnect-sdk + run: cargo publish -p simconnect-sdk --token ${{ secrets.CRATES_IO_TOKEN }} diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 59e988e..0846ed8 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -19,7 +19,7 @@ jobs: name: Audit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d943da4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Change Log + +All notable changes to this project will be documented in this +file. This change log follows the conventions of +[keepachangelog.com][keepachangelog]. + +## [Unreleased] + +## [v0.1.0] - 2022-10-22 + +### Initial Release of simconnect-sdk + +[unreleased]: https://github.com/mihai-dinculescu/simconnect-sdk +[v0.1.0]: https://github.com/mihai-dinculescu/simconnect-sdk/tree/v0.1.0 +[keepachangelog]: https://keepachangelog.com diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ca670a7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing + +Contributions are welcome and encouraged! See [/issues][issues] for ideas, or suggest your own! +If you're thinking to create a PR with large feature/change, please first discuss it in an issue. + +## Releases + +- Update version in `simconnect-sdk-derive/Cargo.toml` +- Update version in `simconnect-sdk/Cargo.toml` (crate + `simconnect-sdk-derive`) +- Update CHANGELOG.md +- Commit +- Add tag + + ```bash + git tag -a vX.X.X + ``` + +- Push + + ```bash + git push --follow-tags + ``` + +- Release\ + Create a [new release][releases]. \ + The `publish.yml` GitHub Action will pick it up and do the actual release to [crates.io][crates_io]. + +[issues]: https://github.com/mihai-dinculescu/simconnect-sdk/issues +[releases]: https://github.com/mihai-dinculescu/simconnect-sdk/releases +[crates_io]: https://crates.io diff --git a/README.md b/README.md index 4a249a2..1ff23aa 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # SimConnect SDK in Rust +[![Crates][crates_badge]][crates] +[![Documentation][documentation_badge]][documentation] [![CI][ci_badge]][ci] - +[![license][license_badge]][license] +[![Crates.io][crates_downloads_badge]][crates]\ An opinionated SimConnect SDK that encapsulates the C API fully and optimizes for developer experience. ## Usage @@ -83,6 +86,10 @@ fn main() -> Result<(), Box> { See [more examples][examples]. +## Contributing + +Contributions are welcome and encouraged! See [/CONTRIBUTING.md][contributing]. + ## Feature table ### General @@ -178,6 +185,19 @@ See [more examples][examples]. | SimConnect_CompleteCustomMissionAction | | | | SimConnect_ExecuteMissionAction | | | +## Credits + +Inspired by [Sequal32/simconnect-rust][inspired_by]. + +[crates_badge]: https://img.shields.io/crates/v/simconnect-sdk.svg +[crates]: https://crates.io/crates/simconnect-sdk +[documentation_badge]: https://docs.rs/simconnect-sdk/badge.svg +[documentation]: https://docs.rs/simconnect-sdk [ci_badge]: https://github.com/mihai-dinculescu/simconnect-sdk/workflows/CI/badge.svg?branch=main [ci]: https://github.com/mihai-dinculescu/simconnect-sdk/actions +[license_badge]: https://img.shields.io/crates/l/simconnect-sdk.svg +[license]: https://github.com/mihai-dinculescu/simconnect-sdk/blob/main/LICENSE +[crates_downloads_badge]: https://img.shields.io/crates/d/simconnect-sdk?label=downloads [examples]: https://github.com/mihai-dinculescu/simconnect-sdk/tree/main/examples +[contributing]: https://github.com/mihai-dinculescu/simconnect-sdk/blob/main/CONTRIBUTING.md +[inspired_by]: https://github.com/Sequal32/simconnect-rust diff --git a/simconnect-sdk-derive/Cargo.toml b/simconnect-sdk-derive/Cargo.toml index e34b23e..517f769 100644 --- a/simconnect-sdk-derive/Cargo.toml +++ b/simconnect-sdk-derive/Cargo.toml @@ -1,12 +1,16 @@ [package] name = "simconnect-sdk-derive" version = "0.1.0" -authors = ["Mihai Dinculescu "] edition = "2021" -description = "Macros of SimConnect SDK for Rust" license = "MIT" +authors = ["Mihai Dinculescu "] +description = "Macros implementation for SimConnect SDK" +keywords = ["simconnect", "MSFS-2020", "simulation", "aerospace"] +categories = ["aerospace", "simulation", "aerospace::simulation", "games"] +readme = "README.md" +repository = "https://github.com/mihai-dinculescu/simconnect-sdk" +include = ["src/**", "LICENSE", "README.md"] autotests = false -publish = false [lib] proc-macro = true diff --git a/simconnect-sdk-derive/LICENSE b/simconnect-sdk-derive/LICENSE new file mode 100644 index 0000000..d3a2e70 --- /dev/null +++ b/simconnect-sdk-derive/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Mihai Dinculescu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/simconnect-sdk-derive/README.md b/simconnect-sdk-derive/README.md new file mode 100644 index 0000000..1ff23aa --- /dev/null +++ b/simconnect-sdk-derive/README.md @@ -0,0 +1,203 @@ +# SimConnect SDK in Rust + +[![Crates][crates_badge]][crates] +[![Documentation][documentation_badge]][documentation] +[![CI][ci_badge]][ci] +[![license][license_badge]][license] +[![Crates.io][crates_downloads_badge]][crates]\ +An opinionated SimConnect SDK that encapsulates the C API fully and optimizes for developer experience. + +## Usage + +```toml +[dependencies] +simconnect-sdk = { version = "0.1", features = ["derive"] } +``` + +```rust +use simconnect_sdk::{Notification, SimConnect, SimConnectObject}; + +/// A data structure that will be used to receive data from SimConnect. +/// See the documentation of `SimConnectObject` for more information on the arguments of the `simconnect` attribute. +#[derive(Debug, Clone, SimConnectObject)] +#[simconnect(period = "second")] +#[allow(dead_code)] +struct AirplaneData { + #[simconnect(name = "TITLE")] + title: 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, +} + +fn main() -> Result<(), Box> { + let client = SimConnect::new("Receiving data example"); + + match client { + Ok(mut client) => { + let mut notifications_received = 0; + + loop { + let notification = client.get_next_dispatch()?; + + match notification { + Some(Notification::Open) => { + println!("Connection opened."); + + // After the connection is successfully open, we register the struct + client.register_object::()?; + } + Some(Notification::Object(data)) => { + if let Ok(airplane_data) = AirplaneData::try_from(&data) { + println!("{airplane_data:?}"); + + notifications_received += 1; + + // After we have received 10 notifications, we unregister the struct + if notifications_received > 10 { + client.unregister_object::()?; + println!("Subscription stopped."); + break; + } + } + } + _ => (), + } + + // sleep for about a frame to reduce CPU usage + std::thread::sleep(std::time::Duration::from_millis(16)); + } + } + Err(e) => { + println!("Error: {e:?}") + } + } + + Ok(()) +} +``` + +See [more examples][examples]. + +## Contributing + +Contributions are welcome and encouraged! See [/CONTRIBUTING.md][contributing]. + +## Feature table + +### General + +| Feature | Status | Comment | +| --------------------------------------- | ------- | ----------- | +| DispatchProc | | | +| SimConnect_Open | ✓ | | +| SimConnect_Close | ✓ | | +| SimConnect_CallDispatch | | | +| SimConnect_GetNextDispatch | ✓ | | +| SimConnect_RequestSystemState | | | +| SimConnect_MapClientEventToSimEvent | - | Coming soon | +| SimConnect_SubscribeToSystemEvent | | | +| SimConnect_SetSystemEventState | | | +| SimConnect_UnsubscribeFromSystemEvent | | | +| SimConnect_SetNotificationGroupPriority | - | Coming soon | + +### Events And Data + +| Feature | Status | Comment | +| -------------------------------------------- | ------- | ----------------------------------- | +| SimConnect_RequestDataOnSimObject | ✓ | Only for SIMCONNECT_OBJECT_ID_USER | +| SimConnect_RequestDataOnSimObjectType | - | Coming soon | +| SimConnect_AddClientEventToNotificationGroup | - | Coming soon | +| SimConnect_RemoveClientEvent | | | +| SimConnect_TransmitClientEvent | | | +| SimConnect_TransmitClientEvent_EX1 | | | +| SimConnect_MapClientDataNameToID | | | +| SimConnect_RequestClientData | | | +| SimConnect_CreateClientData | | | +| SimConnect_AddToClientDataDefinition | | | +| SimConnect_AddToDataDefinition | ✓ | Supports `f64`, `bool` and `String` | +| SimConnect_SetClientData | | | +| SimConnect_SetDataOnSimObject | | | +| SimConnect_ClearClientDataDefinition | | | +| SimConnect_ClearDataDefinition | ✓ | | +| SimConnect_MapInputEventToClientEvent | | | +| SimConnect_RequestNotificationGroup | | | +| SimConnect_ClearInputGroup | | | +| SimConnect_ClearNotificationGroup | | | +| SimConnect_RequestReservedKey | | | +| SimConnect_SetInputGroupPriority | | | +| SimConnect_SetInputGroupState | | | +| SimConnect_RemoveInputEvent | | | + +### AI Objects + +| Feature | Status | Comment | +| ------------------------------------- | ------ | ------- | +| SimConnect_AICreateEnrouteATCAircraft | | | +| SimConnect_AICreateNonATCAircraft | | | +| SimConnect_AICreateParkedATCAircraft | | | +| SimConnect_AICreateSimulatedObject | | | +| SimConnect_AIReleaseControl | | | +| SimConnect_AIRemoveObject | | | +| SimConnect_AISetAircraftFlightPlan | | | + +### Flights + +| Feature | Status | Comment | +| ------------------------- | ------ | ------- | +| SimConnect_FlightLoad | | | +| SimConnect_FlightSave | | | +| SimConnect_FlightPlanLoad | | | + +### Debug + +| Feature | Status | Comment | +| ------------------------------- | ------ | ------- | +| SimConnect_GetLastSentPacketID | | | +| SimConnect_RequestResponseTimes | | | +| SimConnect_InsertString | | | +| SimConnect_RetrieveString | | | + +### Facilities + +| Feature | Status | Comment | +| -------------------------------------- | ------- | ------- | +| SimConnect_AddToFacilityDefinition | | | +| SimConnect_RequestFacilitesList | ✓ | | +| SimConnect_RequestFacilitiesList_EX1 | | | +| SimConnect_RequestFacilityData | | | +| SimConnect_SubscribeToFacilities | ✓ | | +| SimConnect_SubscribeToFacilities_EX1 | | | +| SimConnect_UnsubscribeToFacilities | ✓ | | +| SimConnect_UnsubscribeToFacilities_EX1 | | | + +### Missions + +| Feature | Status | Comment | +| -------------------------------------- | ------ | ------- | +| SimConnect_CompleteCustomMissionAction | | | +| SimConnect_ExecuteMissionAction | | | + +## Credits + +Inspired by [Sequal32/simconnect-rust][inspired_by]. + +[crates_badge]: https://img.shields.io/crates/v/simconnect-sdk.svg +[crates]: https://crates.io/crates/simconnect-sdk +[documentation_badge]: https://docs.rs/simconnect-sdk/badge.svg +[documentation]: https://docs.rs/simconnect-sdk +[ci_badge]: https://github.com/mihai-dinculescu/simconnect-sdk/workflows/CI/badge.svg?branch=main +[ci]: https://github.com/mihai-dinculescu/simconnect-sdk/actions +[license_badge]: https://img.shields.io/crates/l/simconnect-sdk.svg +[license]: https://github.com/mihai-dinculescu/simconnect-sdk/blob/main/LICENSE +[crates_downloads_badge]: https://img.shields.io/crates/d/simconnect-sdk?label=downloads +[examples]: https://github.com/mihai-dinculescu/simconnect-sdk/tree/main/examples +[contributing]: https://github.com/mihai-dinculescu/simconnect-sdk/blob/main/CONTRIBUTING.md +[inspired_by]: https://github.com/Sequal32/simconnect-rust diff --git a/simconnect-sdk-derive/src/fields.rs b/simconnect-sdk-derive/src/fields.rs index 85ef79a..61207db 100644 --- a/simconnect-sdk-derive/src/fields.rs +++ b/simconnect-sdk-derive/src/fields.rs @@ -148,11 +148,8 @@ pub fn extract_attribute_properties( } lit => { return Err(syn::Error::new_spanned( - nv, - format!( - "Expected {:?}, found {:?}", - property.field_type, lit - ), + lit, + format!("Expected {:?}", property.field_type,), ) .to_compile_error()) } diff --git a/simconnect-sdk-derive/tests/04-invalid-values.stderr b/simconnect-sdk-derive/tests/04-invalid-values.stderr index 5260d1a..93772a0 100644 --- a/simconnect-sdk-derive/tests/04-invalid-values.stderr +++ b/simconnect-sdk-derive/tests/04-invalid-values.stderr @@ -1,14 +1,14 @@ -error: Expected Str, found Int(LitInt { token: 123 }) - --> tests/04-invalid-values.rs:5:14 +error: Expected Str + --> tests/04-invalid-values.rs:5:23 | 5 | #[simconnect(period = 123, condition = "none")] - | ^^^^^^^^^^^^ + | ^^^ -error: Expected Str, found Int(LitInt { token: 123 }) - --> tests/04-invalid-values.rs:9:33 +error: Expected Str + --> tests/04-invalid-values.rs:9:45 | 9 | #[simconnect(period = "second", condition = 123)] - | ^^^^^^^^^^^^^^^ + | ^^^ error: `period` must be one of ["once", "visual-frame", "sim-frame", "second"]. --> tests/04-invalid-values.rs:13:14 @@ -22,17 +22,17 @@ error: `condition` must be one of ["none", "changed"]. 17 | #[simconnect(period = "second", condition = "X")] | ^^^^^^^^^^^^^^^ -error: Expected Int, found Str(LitStr { token: "X" }) - --> tests/04-invalid-values.rs:21:33 +error: Expected Int + --> tests/04-invalid-values.rs:21:44 | 21 | #[simconnect(period = "second", interval = "X")] - | ^^^^^^^^^^^^^^ + | ^^^ -error: Expected Int, found Float(LitFloat { token: 0.0 }) - --> tests/04-invalid-values.rs:25:33 +error: Expected Int + --> tests/04-invalid-values.rs:25:44 | 25 | #[simconnect(period = "second", interval = 0.0)] - | ^^^^^^^^^^^^^^ + | ^^^ error: Field type must be one of ["f64", "bool", "String"]. --> tests/04-invalid-values.rs:32:14 diff --git a/simconnect-sdk/Cargo.toml b/simconnect-sdk/Cargo.toml index e43e7fe..2452eae 100644 --- a/simconnect-sdk/Cargo.toml +++ b/simconnect-sdk/Cargo.toml @@ -1,10 +1,15 @@ [package] name = "simconnect-sdk" version = "0.1.0" -authors = ["Mihai Dinculescu "] edition = "2021" -description = "SimConnect SDK for Rust" license = "MIT" +authors = ["Mihai Dinculescu "] +description = "SimConnect SDK" +keywords = ["simconnect", "MSFS-2020", "simulation", "aerospace"] +categories = ["aerospace", "simulation", "aerospace::simulation", "games"] +readme = "README.md" +repository = "https://github.com/mihai-dinculescu/simconnect-sdk" +include = ["src/**", "ffi/**/*", "build.rs", "LICENSE", "README.md"] [features] default = [] @@ -17,7 +22,7 @@ bindgen = "0.61" num_enum = "0.5" tracing = "0.1" thiserror = "1.0" -simconnect-sdk-derive = { path = "../simconnect-sdk-derive", optional = true } +simconnect-sdk-derive = { version = "=0.1.0", path = "../simconnect-sdk-derive", optional = true } # docs.rs-specific configuration [package.metadata.docs.rs] diff --git a/simconnect-sdk/LICENSE b/simconnect-sdk/LICENSE new file mode 100644 index 0000000..d3a2e70 --- /dev/null +++ b/simconnect-sdk/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Mihai Dinculescu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/simconnect-sdk/README.md b/simconnect-sdk/README.md new file mode 100644 index 0000000..1ff23aa --- /dev/null +++ b/simconnect-sdk/README.md @@ -0,0 +1,203 @@ +# SimConnect SDK in Rust + +[![Crates][crates_badge]][crates] +[![Documentation][documentation_badge]][documentation] +[![CI][ci_badge]][ci] +[![license][license_badge]][license] +[![Crates.io][crates_downloads_badge]][crates]\ +An opinionated SimConnect SDK that encapsulates the C API fully and optimizes for developer experience. + +## Usage + +```toml +[dependencies] +simconnect-sdk = { version = "0.1", features = ["derive"] } +``` + +```rust +use simconnect_sdk::{Notification, SimConnect, SimConnectObject}; + +/// A data structure that will be used to receive data from SimConnect. +/// See the documentation of `SimConnectObject` for more information on the arguments of the `simconnect` attribute. +#[derive(Debug, Clone, SimConnectObject)] +#[simconnect(period = "second")] +#[allow(dead_code)] +struct AirplaneData { + #[simconnect(name = "TITLE")] + title: 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, +} + +fn main() -> Result<(), Box> { + let client = SimConnect::new("Receiving data example"); + + match client { + Ok(mut client) => { + let mut notifications_received = 0; + + loop { + let notification = client.get_next_dispatch()?; + + match notification { + Some(Notification::Open) => { + println!("Connection opened."); + + // After the connection is successfully open, we register the struct + client.register_object::()?; + } + Some(Notification::Object(data)) => { + if let Ok(airplane_data) = AirplaneData::try_from(&data) { + println!("{airplane_data:?}"); + + notifications_received += 1; + + // After we have received 10 notifications, we unregister the struct + if notifications_received > 10 { + client.unregister_object::()?; + println!("Subscription stopped."); + break; + } + } + } + _ => (), + } + + // sleep for about a frame to reduce CPU usage + std::thread::sleep(std::time::Duration::from_millis(16)); + } + } + Err(e) => { + println!("Error: {e:?}") + } + } + + Ok(()) +} +``` + +See [more examples][examples]. + +## Contributing + +Contributions are welcome and encouraged! See [/CONTRIBUTING.md][contributing]. + +## Feature table + +### General + +| Feature | Status | Comment | +| --------------------------------------- | ------- | ----------- | +| DispatchProc | | | +| SimConnect_Open | ✓ | | +| SimConnect_Close | ✓ | | +| SimConnect_CallDispatch | | | +| SimConnect_GetNextDispatch | ✓ | | +| SimConnect_RequestSystemState | | | +| SimConnect_MapClientEventToSimEvent | - | Coming soon | +| SimConnect_SubscribeToSystemEvent | | | +| SimConnect_SetSystemEventState | | | +| SimConnect_UnsubscribeFromSystemEvent | | | +| SimConnect_SetNotificationGroupPriority | - | Coming soon | + +### Events And Data + +| Feature | Status | Comment | +| -------------------------------------------- | ------- | ----------------------------------- | +| SimConnect_RequestDataOnSimObject | ✓ | Only for SIMCONNECT_OBJECT_ID_USER | +| SimConnect_RequestDataOnSimObjectType | - | Coming soon | +| SimConnect_AddClientEventToNotificationGroup | - | Coming soon | +| SimConnect_RemoveClientEvent | | | +| SimConnect_TransmitClientEvent | | | +| SimConnect_TransmitClientEvent_EX1 | | | +| SimConnect_MapClientDataNameToID | | | +| SimConnect_RequestClientData | | | +| SimConnect_CreateClientData | | | +| SimConnect_AddToClientDataDefinition | | | +| SimConnect_AddToDataDefinition | ✓ | Supports `f64`, `bool` and `String` | +| SimConnect_SetClientData | | | +| SimConnect_SetDataOnSimObject | | | +| SimConnect_ClearClientDataDefinition | | | +| SimConnect_ClearDataDefinition | ✓ | | +| SimConnect_MapInputEventToClientEvent | | | +| SimConnect_RequestNotificationGroup | | | +| SimConnect_ClearInputGroup | | | +| SimConnect_ClearNotificationGroup | | | +| SimConnect_RequestReservedKey | | | +| SimConnect_SetInputGroupPriority | | | +| SimConnect_SetInputGroupState | | | +| SimConnect_RemoveInputEvent | | | + +### AI Objects + +| Feature | Status | Comment | +| ------------------------------------- | ------ | ------- | +| SimConnect_AICreateEnrouteATCAircraft | | | +| SimConnect_AICreateNonATCAircraft | | | +| SimConnect_AICreateParkedATCAircraft | | | +| SimConnect_AICreateSimulatedObject | | | +| SimConnect_AIReleaseControl | | | +| SimConnect_AIRemoveObject | | | +| SimConnect_AISetAircraftFlightPlan | | | + +### Flights + +| Feature | Status | Comment | +| ------------------------- | ------ | ------- | +| SimConnect_FlightLoad | | | +| SimConnect_FlightSave | | | +| SimConnect_FlightPlanLoad | | | + +### Debug + +| Feature | Status | Comment | +| ------------------------------- | ------ | ------- | +| SimConnect_GetLastSentPacketID | | | +| SimConnect_RequestResponseTimes | | | +| SimConnect_InsertString | | | +| SimConnect_RetrieveString | | | + +### Facilities + +| Feature | Status | Comment | +| -------------------------------------- | ------- | ------- | +| SimConnect_AddToFacilityDefinition | | | +| SimConnect_RequestFacilitesList | ✓ | | +| SimConnect_RequestFacilitiesList_EX1 | | | +| SimConnect_RequestFacilityData | | | +| SimConnect_SubscribeToFacilities | ✓ | | +| SimConnect_SubscribeToFacilities_EX1 | | | +| SimConnect_UnsubscribeToFacilities | ✓ | | +| SimConnect_UnsubscribeToFacilities_EX1 | | | + +### Missions + +| Feature | Status | Comment | +| -------------------------------------- | ------ | ------- | +| SimConnect_CompleteCustomMissionAction | | | +| SimConnect_ExecuteMissionAction | | | + +## Credits + +Inspired by [Sequal32/simconnect-rust][inspired_by]. + +[crates_badge]: https://img.shields.io/crates/v/simconnect-sdk.svg +[crates]: https://crates.io/crates/simconnect-sdk +[documentation_badge]: https://docs.rs/simconnect-sdk/badge.svg +[documentation]: https://docs.rs/simconnect-sdk +[ci_badge]: https://github.com/mihai-dinculescu/simconnect-sdk/workflows/CI/badge.svg?branch=main +[ci]: https://github.com/mihai-dinculescu/simconnect-sdk/actions +[license_badge]: https://img.shields.io/crates/l/simconnect-sdk.svg +[license]: https://github.com/mihai-dinculescu/simconnect-sdk/blob/main/LICENSE +[crates_downloads_badge]: https://img.shields.io/crates/d/simconnect-sdk?label=downloads +[examples]: https://github.com/mihai-dinculescu/simconnect-sdk/tree/main/examples +[contributing]: https://github.com/mihai-dinculescu/simconnect-sdk/blob/main/CONTRIBUTING.md +[inspired_by]: https://github.com/Sequal32/simconnect-rust diff --git a/simconnect-sdk/src/lib.rs b/simconnect-sdk/src/lib.rs index 5eb1fb1..e2c8da9 100644 --- a/simconnect-sdk/src/lib.rs +++ b/simconnect-sdk/src/lib.rs @@ -9,7 +9,73 @@ //! ``` //! //! ```rust,no_run -#![doc = include_str!("../../examples/src/data.rs")] +//! use simconnect_sdk::{Notification, SimConnect, SimConnectObject}; +//! +//! /// A data structure that will be used to receive data from SimConnect. +//! /// See the documentation of `SimConnectObject` for more information on the arguments of the `simconnect` attribute. +//! #[derive(Debug, Clone, SimConnectObject)] +//! #[simconnect(period = "second")] +//! #[allow(dead_code)] +//! struct AirplaneData { +//! #[simconnect(name = "TITLE")] +//! title: 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, +//! } +//! +//! fn main() -> Result<(), Box> { +//! let client = SimConnect::new("Receiving data example"); +//! +//! match client { +//! Ok(mut client) => { +//! let mut notifications_received = 0; +//! +//! loop { +//! let notification = client.get_next_dispatch()?; +//! +//! match notification { +//! Some(Notification::Open) => { +//! println!("Connection opened."); +//! +//! // After the connection is successfully open, we register the struct +//! client.register_object::()?; +//! } +//! Some(Notification::Object(data)) => { +//! if let Ok(airplane_data) = AirplaneData::try_from(&data) { +//! println!("{airplane_data:?}"); +//! +//! notifications_received += 1; +//! +//! // After we have received 10 notifications, we unregister the struct +//! if notifications_received > 10 { +//! client.unregister_object::()?; +//! println!("Subscription stopped."); +//! break; +//! } +//! } +//! } +//! _ => (), +//! } +//! +//! // sleep for about a frame to reduce CPU usage +//! std::thread::sleep(std::time::Duration::from_millis(16)); +//! } +//! } +//! Err(e) => { +//! println!("Error: {e:?}") +//! } +//! } +//! +//! Ok(()) +//! } //! ``` //! //! See [more examples](https://github.com/mihai-dinculescu/simconnect-sdk/tree/main/examples). diff --git a/simconnect-sdk/src/simconnect/base.rs b/simconnect-sdk/src/simconnect/base.rs index 3417979..1c18c4d 100644 --- a/simconnect-sdk/src/simconnect/base.rs +++ b/simconnect-sdk/src/simconnect/base.rs @@ -10,7 +10,73 @@ use crate::{ /// # Example /// /// ```rust,no_run -#[doc = include_str!("../../../examples/src/data.rs")] +/// use simconnect_sdk::{Notification, SimConnect, SimConnectObject}; +/// +/// /// A data structure that will be used to receive data from SimConnect. +/// /// See the documentation of `SimConnectObject` for more information on the arguments of the `simconnect` attribute. +/// #[derive(Debug, Clone, SimConnectObject)] +/// #[simconnect(period = "second")] +/// #[allow(dead_code)] +/// struct AirplaneData { +/// #[simconnect(name = "TITLE")] +/// title: 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, +/// } +/// +/// fn main() -> Result<(), Box> { +/// let client = SimConnect::new("Receiving data example"); +/// +/// match client { +/// Ok(mut client) => { +/// let mut notifications_received = 0; +/// +/// loop { +/// let notification = client.get_next_dispatch()?; +/// +/// match notification { +/// Some(Notification::Open) => { +/// println!("Connection opened."); +/// +/// // After the connection is successfully open, we register the struct +/// client.register_object::()?; +/// } +/// Some(Notification::Object(data)) => { +/// if let Ok(airplane_data) = AirplaneData::try_from(&data) { +/// println!("{airplane_data:?}"); +/// +/// notifications_received += 1; +/// +/// // After we have received 10 notifications, we unregister the struct +/// if notifications_received > 10 { +/// client.unregister_object::()?; +/// println!("Subscription stopped."); +/// break; +/// } +/// } +/// } +/// _ => (), +/// } +/// +/// // sleep for about a frame to reduce CPU usage +/// std::thread::sleep(std::time::Duration::from_millis(16)); +/// } +/// } +/// Err(e) => { +/// println!("Error: {e:?}") +/// } +/// } +/// +/// Ok(()) +/// } /// ``` #[derive(Debug)] pub struct SimConnect {