Compare commits

...

10 Commits

Author SHA1 Message Date
bee3553d9e Updated SDK
Some checks failed
CI / Rust checks (push) Failing after 6s
2024-10-20 12:01:48 +02:00
Mihai Dinculescu
856656e23b Update crates 2023-05-01 19:13:42 +01:00
Mihai Dinculescu
d89fa524c2 Rework events and add proper support for client events
Added

- Client events are now implemented through `SimConnect::subscribe_to_client_event`, `SimConnect::unsubscribe_from_client_event` and `SimConnect::unsubscribe_from_all_client_events`.
- `subscribe_to_client_events.rs` example has been added.
- `SimConnectError::EventAlreadySubscribedTo` and `SimConnectError::EventNotSubscribedTo` error variants have been added.

Changed

- A second call to `SimConnect::subscribe_to_system_event` for the same event will now return an error of type `SimConnectError::EventAlreadySubscribedTo` instead of `SimConnectError::SimConnectException`.
- The call to `SimConnect::unsubscribe_from_system_event` is now a NOOP when the system event is not subscribed to.
- `SimConnectError::UnimplementedMessageType` has been renamed to `SimConnectError::UnimplementedNotification`.

Removed

- `SimConnect::register_event` has been replaced by the new client event functions.
- `NotificationGroup` has been removed in favor of an internally managed notification group.
2023-05-01 19:13:30 +01:00
Mihai Dinculescu
85e5341599 Announce v0.2.2 2023-02-22 19:11:21 +00:00
Mihai Dinculescu
651aadd70f Update crates 2023-02-22 18:41:51 +00:00
Mihai Dinculescu
93ab001d48 Automatically clean up request_facilities_list requests once completed 2023-02-22 18:41:01 +00:00
Mihai Dinculescu
e074d708d8 Updated to MSFS SDK v0.20.5.0 2023-02-09 10:34:45 +00:00
Mihai Dinculescu
88d9f78e59 Update crates 2023-02-09 10:34:40 +00:00
dependabot[bot]
9f569d49fa Bump bindgen from 0.61.0 to 0.62.0
Bumps [bindgen](https://github.com/rust-lang/rust-bindgen) from 0.61.0 to 0.62.0.
- [Release notes](https://github.com/rust-lang/rust-bindgen/releases)
- [Changelog](https://github.com/rust-lang/rust-bindgen/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/rust-bindgen/compare/v0.61.0...v0.62.0)

---
updated-dependencies:
- dependency-name: bindgen
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-19 19:37:28 +00:00
Mihai Dinculescu
63086c5b9b Announce v0.2.1 2022-10-29 15:52:37 +01:00
32 changed files with 1340 additions and 596 deletions

View File

@@ -8,6 +8,34 @@ file. This change log follows the conventions of
### Added ### Added
- Client events are now implemented through `SimConnect::subscribe_to_client_event`, `SimConnect::unsubscribe_from_client_event` and `SimConnect::unsubscribe_from_all_client_events`.
- `subscribe_to_client_events.rs` example has been added.
- `SimConnectError::EventAlreadySubscribedTo` and `SimConnectError::EventNotSubscribedTo` error variants have been added.
### Changed
- A second call to `SimConnect::subscribe_to_system_event` for the same event will now return an error of type `SimConnectError::EventAlreadySubscribedTo` instead of `SimConnectError::SimConnectException`.
- The call to `SimConnect::unsubscribe_from_system_event` is now a NOOP when the system event is not subscribed to.
- `SimConnectError::UnimplementedMessageType` has been renamed to `SimConnectError::UnimplementedNotification`.
### Removed
- `SimConnect::register_event` has been replaced by the new client event functions.
- `NotificationGroup` has been removed in favor of an internally managed notification group.
## [v0.2.2] - 2023-02-22
### Changed
- Updated to MSFS SDK v0.20.5.0.
- `SimConnect::get_next_dispatch` now takes a `&mut self` in order to be able to clean up requests that have returned all the results they ever will.
### Fixed
- `SimConnect::request_facilities_list` calls now automatically clean up the request after all the data is received.
## [v0.2.1] - 2022-10-29
### Added
- `#[derive(PartialEq)]` has been added to `Condition`, `DataType`, `FacilityType`, `NotificationGroup`, `Period`, `ViewType`, `ClientEvent`, `SystemEventRequest` and `SystemEvent`. - `#[derive(PartialEq)]` has been added to `Condition`, `DataType`, `FacilityType`, `NotificationGroup`, `Period`, `ViewType`, `ClientEvent`, `SystemEventRequest` and `SystemEvent`.
- `#[derive(Eq)]` has been added to `Condition`, `DataType`, `FacilityType`, `NotificationGroup`, `Period`, `ViewType`, `ClientEvent` and `SystemEventRequest`. - `#[derive(Eq)]` has been added to `Condition`, `DataType`, `FacilityType`, `NotificationGroup`, `Period`, `ViewType`, `ClientEvent` and `SystemEventRequest`.
@@ -61,6 +89,8 @@ file. This change log follows the conventions of
### Initial Release of simconnect-sdk ### Initial Release of simconnect-sdk
[unreleased]: https://github.com/mihai-dinculescu/simconnect-sdk-rs [unreleased]: https://github.com/mihai-dinculescu/simconnect-sdk-rs
[v0.2.2]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.2.2
[v0.2.1]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.2.1
[v0.2.0]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.2.0 [v0.2.0]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.2.0
[v0.1.3]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.1.3 [v0.1.3]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.1.3
[v0.1.2]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.1.2 [v0.1.2]: https://github.com/mihai-dinculescu/simconnect-sdk-rs/tree/v0.1.2

View File

@@ -5,9 +5,9 @@ If you're thinking to create a PR with large feature/change, please first discus
## Releases ## Releases
- Update version in `examples/Cargo.toml`
- Update version in `simconnect-sdk/Cargo.toml` (crate + `simconnect-sdk-derive`)
- Update version in `simconnect-sdk-derive/Cargo.toml` - Update version in `simconnect-sdk-derive/Cargo.toml`
- Update version in `simconnect-sdk/Cargo.toml` (crate + `simconnect-sdk-derive`)
- Update version in `examples/Cargo.toml`
- Update CHANGELOG.md - Update CHANGELOG.md
- Commit - Commit
- Add tag - Add tag

240
Cargo.lock generated
View File

@@ -3,10 +3,25 @@
version = 3 version = 3
[[package]] [[package]]
name = "bindgen" name = "autocfg"
version = "0.61.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a022e58a142a46fea340d68012b9201c094e93ec3d033a944a24f8fd4a4f09a" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "basic-toml"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c0de75129aa8d0cceaf750b89013f0e08804d6ec61416da787b35ad0d7cddf1"
dependencies = [
"serde",
]
[[package]]
name = "bindgen"
version = "0.65.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cexpr", "cexpr",
@@ -15,12 +30,13 @@ dependencies = [
"lazycell", "lazycell",
"log", "log",
"peeking_take_while", "peeking_take_while",
"prettyplease",
"proc-macro2", "proc-macro2",
"quote", "quote",
"regex", "regex",
"rustc-hash", "rustc-hash",
"shlex", "shlex",
"syn", "syn 2.0.15",
"which", "which",
] ]
@@ -47,9 +63,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clang-sys" name = "clang-sys"
version = "1.4.0" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [ dependencies = [
"glob", "glob",
"libc", "libc",
@@ -58,27 +74,43 @@ dependencies = [
[[package]] [[package]]
name = "dissimilar" name = "dissimilar"
version = "1.0.4" version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5" checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e"
[[package]] [[package]]
name = "either" name = "either"
version = "1.8.0" version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]] [[package]]
name = "glob" name = "glob"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.4" version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
@@ -94,15 +126,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.137" version = "0.2.142"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
[[package]] [[package]]
name = "libloading" name = "libloading"
version = "0.7.3" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"winapi", "winapi",
@@ -140,9 +172,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "nom" name = "nom"
version = "7.1.1" version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [ dependencies = [
"memchr", "memchr",
"minimal-lexical", "minimal-lexical",
@@ -160,30 +192,30 @@ dependencies = [
[[package]] [[package]]
name = "num_enum" name = "num_enum"
version = "0.5.7" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1"
dependencies = [ dependencies = [
"num_enum_derive", "num_enum_derive",
] ]
[[package]] [[package]]
name = "num_enum_derive" name = "num_enum_derive"
version = "0.5.7" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6"
dependencies = [ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.15",
] ]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.16.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "overload" name = "overload"
@@ -204,41 +236,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]] [[package]]
name = "proc-macro-crate" name = "prettyplease"
version = "1.2.1" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" checksum = "1ceca8aaf45b5c46ec7ed39fff75f57290368c1846d33d24a122ca81416ab058"
dependencies = [
"proc-macro2",
"syn 2.0.15",
]
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"thiserror", "toml_edit",
"toml",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.47" version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.21" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.6.0" version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
dependencies = [ dependencies = [
"regex-syntax", "regex-syntax 0.7.1",
] ]
[[package]] [[package]]
@@ -247,14 +288,20 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [ dependencies = [
"regex-syntax", "regex-syntax 0.6.29",
] ]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.27" version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
@@ -264,32 +311,32 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.11" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.147" version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.147" version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.15",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.87" version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@@ -313,7 +360,7 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]] [[package]]
name = "simconnect-sdk" name = "simconnect-sdk"
version = "0.2.0" version = "0.2.2"
dependencies = [ dependencies = [
"bindgen", "bindgen",
"num_enum", "num_enum",
@@ -324,19 +371,19 @@ dependencies = [
[[package]] [[package]]
name = "simconnect-sdk-derive" name = "simconnect-sdk-derive"
version = "0.2.0" version = "0.2.2"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"simconnect-sdk", "simconnect-sdk",
"syn", "syn 1.0.109",
"trybuild", "trybuild",
] ]
[[package]] [[package]]
name = "simconnect-sdk-examples" name = "simconnect-sdk-examples"
version = "0.2.0" version = "0.2.2"
dependencies = [ dependencies = [
"simconnect-sdk", "simconnect-sdk",
"tracing", "tracing",
@@ -351,9 +398,20 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.103" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -362,49 +420,58 @@ dependencies = [
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.1.3" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.37" version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.37" version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.15",
] ]
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.1.4" version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [ dependencies = [
"cfg-if",
"once_cell", "once_cell",
] ]
[[package]] [[package]]
name = "toml" name = "toml_datetime"
version = "0.5.9" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
[[package]]
name = "toml_edit"
version = "0.19.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
dependencies = [ dependencies = [
"serde", "indexmap",
"toml_datetime",
"winnow",
] ]
[[package]] [[package]]
@@ -421,13 +488,13 @@ dependencies = [
[[package]] [[package]]
name = "tracing-attributes" name = "tracing-attributes"
version = "0.1.23" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.15",
] ]
[[package]] [[package]]
@@ -453,9 +520,9 @@ dependencies = [
[[package]] [[package]]
name = "tracing-subscriber" name = "tracing-subscriber"
version = "0.3.16" version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
dependencies = [ dependencies = [
"matchers", "matchers",
"nu-ansi-term", "nu-ansi-term",
@@ -471,10 +538,11 @@ dependencies = [
[[package]] [[package]]
name = "trybuild" name = "trybuild"
version = "1.0.71" version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea496675d71016e9bc76aa42d87f16aefd95447cc5818e671e12b2d7e269075d" checksum = "501dbdbb99861e4ab6b60eb6a7493956a9defb644fd034bc4a5ef27c693c8a3a"
dependencies = [ dependencies = [
"basic-toml",
"dissimilar", "dissimilar",
"glob", "glob",
"once_cell", "once_cell",
@@ -482,14 +550,13 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"termcolor", "termcolor",
"toml",
] ]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.5" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "valuable" name = "valuable"
@@ -499,9 +566,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "which" name = "which"
version = "4.3.0" version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
dependencies = [ dependencies = [
"either", "either",
"libc", "libc",
@@ -538,3 +605,12 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winnow"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5617da7e1f97bf363947d767b91aaf3c2bbc19db7fda9c65af1278713d58e0a2"
dependencies = [
"memchr",
]

View File

@@ -2,47 +2,47 @@
## General ## General
| Feature | Status | Comment | | Feature | Status | Comment |
| --------------------------------------- | ------- | ------- | | --------------------------------------- | ------- | -------------------------------------------- |
| DispatchProc | | | | DispatchProc | | |
| SimConnect_Open | &check; | | | SimConnect_Open | &check; | |
| SimConnect_Close | &check; | | | SimConnect_Close | &check; | |
| SimConnect_CallDispatch | | | | SimConnect_CallDispatch | | |
| SimConnect_GetNextDispatch | &check; | | | SimConnect_GetNextDispatch | &check; | |
| SimConnect_RequestSystemState | | | | SimConnect_RequestSystemState | | |
| SimConnect_MapClientEventToSimEvent | - | WIP | | SimConnect_MapClientEventToSimEvent | &check; | Encapsulated by `subscribe_to_client_event`. |
| SimConnect_SubscribeToSystemEvent | &check; | | | SimConnect_SubscribeToSystemEvent | &check; | |
| SimConnect_SetSystemEventState | | | | SimConnect_SetSystemEventState | | |
| SimConnect_UnsubscribeFromSystemEvent | &check; | | | SimConnect_UnsubscribeFromSystemEvent | &check; | |
| SimConnect_SetNotificationGroupPriority | - | WIP | | SimConnect_SetNotificationGroupPriority | &check; | Encapsulated by `subscribe_to_client_event`. |
## Events And Data ## Events And Data
| Feature | Status | Comment | | Feature | Status | Comment |
| -------------------------------------------- | ------- | ----------------------------------- | | -------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| SimConnect_RequestDataOnSimObject | &check; | Only for SIMCONNECT_OBJECT_ID_USER | | SimConnect_RequestDataOnSimObject | &check; | Only for `SIMCONNECT_OBJECT_ID_USER`. |
| SimConnect_RequestDataOnSimObjectType | | | | SimConnect_RequestDataOnSimObjectType | | |
| SimConnect_AddClientEventToNotificationGroup | - | WIP | | SimConnect_AddClientEventToNotificationGroup | &check; | Encapsulated by `subscribe_to_client_event`. |
| SimConnect_RemoveClientEvent | | | | SimConnect_RemoveClientEvent | &check; | |
| SimConnect_TransmitClientEvent | | | | SimConnect_TransmitClientEvent | | |
| SimConnect_TransmitClientEvent_EX1 | | | | SimConnect_TransmitClientEvent_EX1 | | |
| SimConnect_MapClientDataNameToID | | | | SimConnect_MapClientDataNameToID | | |
| SimConnect_RequestClientData | | | | SimConnect_RequestClientData | | |
| SimConnect_CreateClientData | | | | SimConnect_CreateClientData | | |
| SimConnect_AddToClientDataDefinition | | | | SimConnect_AddToClientDataDefinition | | |
| SimConnect_AddToDataDefinition | &check; | Supports `f64`, `bool` and `String` | | SimConnect_AddToDataDefinition | &check; | Encapsulated by `register_object` and the `simconnect` macro. Supports `f64`, `bool` and `String`. |
| SimConnect_SetClientData | | | | SimConnect_SetClientData | | |
| SimConnect_SetDataOnSimObject | | | | SimConnect_SetDataOnSimObject | | |
| SimConnect_ClearClientDataDefinition | | | | SimConnect_ClearClientDataDefinition | | |
| SimConnect_ClearDataDefinition | &check; | | | SimConnect_ClearDataDefinition | &check; | |
| SimConnect_MapInputEventToClientEvent | | | | SimConnect_MapInputEventToClientEvent | | |
| SimConnect_RequestNotificationGroup | | | | SimConnect_RequestNotificationGroup | | |
| SimConnect_ClearInputGroup | | | | SimConnect_ClearInputGroup | | |
| SimConnect_ClearNotificationGroup | | | | SimConnect_ClearNotificationGroup | &check; | Implemented by `unsubscribe_from_all_client_events`. |
| SimConnect_RequestReservedKey | | | | SimConnect_RequestReservedKey | | |
| SimConnect_SetInputGroupPriority | | | | SimConnect_SetInputGroupPriority | | |
| SimConnect_SetInputGroupState | | | | SimConnect_SetInputGroupState | | |
| SimConnect_RemoveInputEvent | | | | SimConnect_RemoveInputEvent | | |
## AI Objects ## AI Objects

6
TODO.md Normal file
View File

@@ -0,0 +1,6 @@
# TODO
- SimConnect_RequestDataOnSimObjectType
- add support to request other object ids
- rename request_id to object_id
- type exceptions

View File

@@ -1,10 +1,12 @@
[package] [package]
name = "simconnect-sdk-examples" name = "simconnect-sdk-examples"
version = "0.2.0" version = "0.2.2"
authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"]
edition = "2021" edition = "2021"
description = "SimConnect SDK Examples"
license = "MIT" license = "MIT"
authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"]
description = "SimConnect SDK Examples"
readme = "README.md"
repository = "https://github.com/mihai-dinculescu/simconnect-sdk-rs"
publish = false publish = false
[[bin]] [[bin]]
@@ -28,8 +30,12 @@ name = "facilities"
path = "src/facilities.rs" path = "src/facilities.rs"
[[bin]] [[bin]]
name = "system_events" name = "subscribe_to_client_events"
path = "src/system_events.rs" path = "src/subscribe_to_client_events.rs"
[[bin]]
name = "subscribe_to_system_events"
path = "src/subscribe_to_system_events.rs"
[dependencies] [dependencies]
tracing = "0.1" tracing = "0.1"

View File

@@ -45,8 +45,14 @@ cargo run --bin data_multiple_objects
cargo run --bin facilities cargo run --bin facilities
``` ```
## Receiving system events ## Subscribe to client events
```bash ```bash
cargo run --bin system_events cargo run --bin subscribe_to_client_events
```
## Subscribe to system events
```bash
cargo run --bin subscribe_to_system_events
``` ```

View File

@@ -24,41 +24,41 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Some(Notification::AirportList(data)) => { Some(Notification::AirportList(data)) => {
for record in data { for record in data {
// The returned list is quite large, so we look for a particular record // The returned list is quite large, so we look for a particular record
if record.icao == "EGSC" { // if record.icao == "EGSC" {
println!("{record:?}"); // println!("{record:?}");
// we've got the entry we're interesting in - we can unsubscribe now // // there's no need to unsubscribe
client.unsubscribe_to_facilities(FacilityType::Airport)?; // // because this is a one-off request, not a subscription
} // }
} }
} }
Some(Notification::WaypointList(data)) => { Some(Notification::WaypointList(data)) => {
for record in data { for record in data {
// The returned list is quite large, so we look for a particular record // The returned list is quite large, so we look for a particular record
if record.icao == "BRAIN" { // if record.icao == "BRAIN" {
println!("{record:?}"); // println!("{record:?}");
// we've got the entry we're interesting in - we can unsubscribe now // // we've got the entry we're interesting in - we can unsubscribe now
client.unsubscribe_to_facilities(FacilityType::Waypoint)?; // client.unsubscribe_to_facilities(FacilityType::Waypoint)?;
} // }
} }
} }
Some(Notification::NdbList(data)) => { Some(Notification::NdbList(data)) => {
for record in data { for record in data {
// The returned list is quite large, so we look for a particular record // The returned list is quite large, so we look for a particular record
if record.icao == "CAM" { // if record.icao == "CAM" {
println!("{record:?}"); // println!("{record:?}");
// we've got the entry we're interesting in - we can unsubscribe now // // we've got the entry we're interesting in - we can unsubscribe now
client.unsubscribe_to_facilities(FacilityType::NDB)?; // client.unsubscribe_to_facilities(FacilityType::NDB)?;
} // }
} }
} }
Some(Notification::VorList(data)) => { Some(Notification::VorList(data)) => {
for record in data { for record in data {
// The returned list is quite large, so we look for a particular record // The returned list is quite large, so we look for a particular record
if record.icao == "LON" { // if record.icao == "LON" {
println!("{record:?}"); // println!("{record:?}");
// we've got the entry we're interesting in - we can unsubscribe now // // we've got the entry we're interesting in - we can unsubscribe now
client.unsubscribe_to_facilities(FacilityType::VOR)?; // client.unsubscribe_to_facilities(FacilityType::VOR)?;
} // }
} }
} }
_ => (), _ => (),

View File

@@ -0,0 +1,62 @@
use simconnect_sdk::{ClientEvent, ClientEventRequest, Notification, SimConnect};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = SimConnect::new("Client Events example");
let mut throttle_events_received = 0;
let mut elevator_events_received = 0;
match client {
Ok(mut client) => loop {
let notification = client.get_next_dispatch()?;
match notification {
Some(Notification::Open) => {
println!("Connection opened.");
// After the connection is successfully open
// We subscribe to the client events we're interested in
client.subscribe_to_client_event(ClientEventRequest::Throttle1Set)?;
client.subscribe_to_client_event(ClientEventRequest::AxisElevatorSet)?;
}
Some(Notification::ClientEvent(event)) => match event {
ClientEvent::Throttle1Set { value } => {
println!("Throttle1Set: {value}");
throttle_events_received += 1;
if throttle_events_received >= 9 {
// We unsubscribe from the client event after we receive 10 of them
// This might run multiple times if there are more events queued up
println!("Unsubscribing from Throttle1Set...");
client
.unsubscribe_from_client_event(ClientEventRequest::Throttle1Set)?;
}
}
ClientEvent::AxisElevatorSet { value } => {
println!("AxisElevatorSet: {value}");
elevator_events_received += 1;
if elevator_events_received >= 9 {
// We unsubscribe from the client event after we receive 10 of them
// This might run multiple times if there are more events queued up
println!("Unsubscribing from AxisElevatorSet...");
client.unsubscribe_from_client_event(
ClientEventRequest::AxisElevatorSet,
)?;
}
}
_ => {}
},
_ => (),
}
// sleep for about a frame to reduce CPU usage
std::thread::sleep(std::time::Duration::from_millis(16));
},
Err(e) => {
println!("Error: {e:?}")
}
}
Ok(())
}

View File

@@ -1,7 +1,7 @@
use simconnect_sdk::{Notification, SimConnect, SystemEvent, SystemEventRequest}; use simconnect_sdk::{Notification, SimConnect, SystemEvent, SystemEventRequest};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = SimConnect::new("System events example"); let client = SimConnect::new("System Events example");
match client { match client {
Ok(mut client) => loop { Ok(mut client) => loop {

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "simconnect-sdk-derive" name = "simconnect-sdk-derive"
version = "0.2.0" version = "0.2.2"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"] authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"]
@@ -23,7 +23,7 @@ path = "tests/run.rs"
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = "1.0" syn = "1.0"
once_cell = "1.7" once_cell = "1.17"
[dev-dependencies] [dev-dependencies]
simconnect-sdk = { path = "../simconnect-sdk" } simconnect-sdk = { path = "../simconnect-sdk" }

View File

@@ -51,7 +51,7 @@ pub fn derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let name_ident = &ast.ident; let name_ident = &ast.ident;
let packed_ident = syn::Ident::new(&format!("{}CPacked", name_ident), name_ident.span()); let packed_ident = syn::Ident::new(&format!("{name_ident}CPacked"), name_ident.span());
let fields = if let syn::Data::Struct(syn::DataStruct { let fields = if let syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }), fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }),

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "simconnect-sdk" name = "simconnect-sdk"
version = "0.2.0" version = "0.2.2"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"] authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"]
@@ -16,13 +16,13 @@ default = []
derive = ["simconnect-sdk-derive"] derive = ["simconnect-sdk-derive"]
[build-dependencies] [build-dependencies]
bindgen = "0.61" bindgen = "0.65"
[dependencies] [dependencies]
num_enum = "0.5" num_enum = "0.6"
tracing = "0.1" tracing = "0.1"
thiserror = "1.0" thiserror = "1.0"
simconnect-sdk-derive = { version = "=0.2.0", path = "../simconnect-sdk-derive", optional = true } simconnect-sdk-derive = { version = "=0.2.2", path = "../simconnect-sdk-derive", optional = true }
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["derive"] features = ["derive"]

View File

@@ -25,10 +25,12 @@ fn main() {
.allowlist_function("SimConnect_AddToDataDefinition") .allowlist_function("SimConnect_AddToDataDefinition")
.allowlist_function("SimConnect_CallDispatch") .allowlist_function("SimConnect_CallDispatch")
.allowlist_function("SimConnect_ClearDataDefinition") .allowlist_function("SimConnect_ClearDataDefinition")
.allowlist_function("SimConnect_ClearNotificationGroup")
.allowlist_function("SimConnect_Close") .allowlist_function("SimConnect_Close")
.allowlist_function("SimConnect_GetNextDispatch") .allowlist_function("SimConnect_GetNextDispatch")
.allowlist_function("SimConnect_MapClientEventToSimEvent") .allowlist_function("SimConnect_MapClientEventToSimEvent")
.allowlist_function("SimConnect_Open") .allowlist_function("SimConnect_Open")
.allowlist_function("SimConnect_RemoveClientEvent")
.allowlist_function("SimConnect_RequestDataOnSimObject") .allowlist_function("SimConnect_RequestDataOnSimObject")
.allowlist_function("SimConnect_RequestFacilitiesList") .allowlist_function("SimConnect_RequestFacilitiesList")
.allowlist_function("SimConnect_SetNotificationGroupPriority") .allowlist_function("SimConnect_SetNotificationGroupPriority")
@@ -52,6 +54,11 @@ fn main() {
.allowlist_type("SIMCONNECT_RECV_WAYPOINT_LIST") .allowlist_type("SIMCONNECT_RECV_WAYPOINT_LIST")
.allowlist_type("SIMCONNECT_RECV") .allowlist_type("SIMCONNECT_RECV")
.allowlist_var("SIMCONNECT_DATA_REQUEST_FLAG_CHANGED") .allowlist_var("SIMCONNECT_DATA_REQUEST_FLAG_CHANGED")
.allowlist_var("SIMCONNECT_GROUP_PRIORITY_DEFAULT")
.allowlist_var("SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE")
.allowlist_var("SIMCONNECT_GROUP_PRIORITY_HIGHEST")
.allowlist_var("SIMCONNECT_GROUP_PRIORITY_LOWEST")
.allowlist_var("SIMCONNECT_GROUP_PRIORITY_STANDARD")
.allowlist_var("SIMCONNECT_OBJECT_ID_USER") .allowlist_var("SIMCONNECT_OBJECT_ID_USER")
.allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME") .allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME")
.allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE") .allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE")

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
0.19.3.0 0.24.3.0

View File

@@ -0,0 +1,194 @@
use std::os::raw::c_char;
use crate::{bindings, SimConnectError};
// System Events start from 0 so we have to stagger the values to avoid collisions.
pub(crate) const CLIENT_EVENT_DISCRIMINANT_START: u32 = 1024;
/// SimConnect Client Event Request.
///
/// Defined by <https://www.prepar3d.com/SDKv5/sdk/references/variables/event_ids.html>.
/// Extended by <https://docs.flightsimulator.com/html/Programming_Tools/Event_IDs/Event_IDs.htm>.
#[derive(Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive)]
#[repr(u32)]
#[non_exhaustive]
pub enum ClientEventRequest {
// ---------------
// Aircraft Engine
// ---------------
/// Set throttle 1 exactly (0 to 16383).
Throttle1Set = CLIENT_EVENT_DISCRIMINANT_START,
/// Set throttle 2 exactly (0 to 16383).
Throttle2Set,
/// Set throttle 3 exactly (0 to 16383).
Throttle3Set,
/// Set throttle 4 exactly (0 to 16383).
Throttle4Set,
// ---------------
// Aircraft Flight Controls
// ---------------
/// Sets elevator position (-16383 - +16383).
AxisElevatorSet,
// ---------------
// Aircraft Miscellaneous Systems
// ---------------
/// Increment brake pressure. Note: These are simulated spring-loaded toe brakes, which will bleed back to zero over time.
Brakes,
/// Increments left brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
BrakesLeft,
/// Increments right brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
BrakesRight,
/// Sets left brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
AxisLeftBrakeSet,
/// Sets right brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
AxisRightBrakeSet,
/// Toggles parking brake on/off.
ParkingBrakes,
}
impl ClientEventRequest {
pub(crate) fn into_c_char(self) -> *const c_char {
match self {
// Aircraft Engine
Self::Throttle1Set => "THROTTLE1_SET\0".as_ptr() as *const c_char,
Self::Throttle2Set => "THROTTLE2_SET\0".as_ptr() as *const c_char,
Self::Throttle3Set => "THROTTLE3_SET\0".as_ptr() as *const c_char,
Self::Throttle4Set => "THROTTLE4_SET\0".as_ptr() as *const c_char,
// Aircraft Flight Controls
Self::AxisElevatorSet => "AXIS_ELEVATOR_SET\0".as_ptr() as *const c_char,
// Aircraft Miscellaneous Systems
Self::Brakes => "BRAKES\0".as_ptr() as *const c_char,
Self::BrakesLeft => "BRAKES_LEFT\0".as_ptr() as *const c_char,
Self::BrakesRight => "BRAKES_RIGHT\0".as_ptr() as *const c_char,
Self::AxisLeftBrakeSet => "AXIS_LEFT_BRAKE_SET\0".as_ptr() as *const c_char,
Self::AxisRightBrakeSet => "AXIS_RIGHT_BRAKE_SET\0".as_ptr() as *const c_char,
Self::ParkingBrakes => "PARKING_BRAKES\0".as_ptr() as *const c_char,
}
}
}
/// SimConnect Client Event.
///
/// Defined by <https://www.prepar3d.com/SDKv5/sdk/references/variables/event_ids.html>.
/// Extended by <https://docs.flightsimulator.com/html/Programming_Tools/Event_IDs/Event_IDs.htm>.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ClientEvent {
// ---------------
// Aircraft Engine
// ---------------
/// Set throttle 1 exactly (0 to 16383).
Throttle1Set {
/// -16383 (0 throttle) to +16383 (max throttle).
value: i32,
},
/// Set throttle 2 exactly (0 to 16383).
Throttle2Set {
/// -16383 (0 throttle) to +16383 (max throttle).
value: i32,
},
/// Set throttle 3 exactly (0 to 16383).
Throttle3Set {
/// -16383 (0 throttle) to +16383 (max throttle).
value: i32,
},
/// Set throttle 4 exactly (0 to 16383).
Throttle4Set {
/// -16383 (0 throttle) to +16383 (max throttle).
value: i32,
},
// ---------------
// Aircraft Flight Controls
// ---------------
/// Sets elevator position (-16383 - +16383).
AxisElevatorSet {
/// -16383 (full down) to +16383 (full up).
value: i32,
},
// ---------------
// Aircraft Miscellaneous Systems
// ---------------
/// Increment brake pressure. Note: These are simulated spring-loaded toe brakes, which will bleed back to zero over time.
Brakes,
/// Increments left brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
BrakesLeft,
/// Increments right brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
BrakesRight,
/// Sets left brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
AxisLeftBrakeSet {
/// -16383 (0 brakes) to +16383 (max brakes).
value: i32,
},
/// Sets right brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
AxisRightBrakeSet {
/// -16383 (0 brakes) to +16383 (max brakes).
value: i32,
},
/// Toggles parking brake on/off.
ParkingBrakes,
}
impl TryFrom<&bindings::SIMCONNECT_RECV_EVENT> for ClientEvent {
type Error = SimConnectError;
fn try_from(event: &bindings::SIMCONNECT_RECV_EVENT) -> Result<Self, Self::Error> {
let request = ClientEventRequest::try_from(event.uEventID)
.map_err(|_| SimConnectError::UnimplementedEventType(event.uEventID))?;
match request {
// Aircraft Engine
ClientEventRequest::Throttle1Set => Ok(Self::Throttle1Set {
value: event.dwData as i32,
}),
ClientEventRequest::Throttle2Set => Ok(Self::Throttle2Set {
value: event.dwData as i32,
}),
ClientEventRequest::Throttle3Set => Ok(Self::Throttle3Set {
value: event.dwData as i32,
}),
ClientEventRequest::Throttle4Set => Ok(Self::Throttle4Set {
value: event.dwData as i32,
}),
// Aircraft Flight Controls
ClientEventRequest::AxisElevatorSet => Ok(Self::AxisElevatorSet {
value: event.dwData as i32,
}),
// Aircraft Miscellaneous Systems
ClientEventRequest::Brakes => Ok(Self::Brakes),
ClientEventRequest::BrakesLeft => Ok(Self::BrakesLeft),
ClientEventRequest::BrakesRight => Ok(Self::BrakesRight),
ClientEventRequest::AxisLeftBrakeSet => Ok(Self::AxisLeftBrakeSet {
value: event.dwData as i32,
}),
ClientEventRequest::AxisRightBrakeSet => Ok(Self::AxisRightBrakeSet {
value: event.dwData as i32,
}),
ClientEventRequest::ParkingBrakes => Ok(Self::ParkingBrakes),
}
}
}
impl From<ClientEvent> for (ClientEventRequest, i32) {
fn from(event: ClientEvent) -> Self {
match event {
// Aircraft Engine
ClientEvent::Throttle1Set { value } => (ClientEventRequest::Throttle1Set, value),
ClientEvent::Throttle2Set { value } => (ClientEventRequest::Throttle2Set, value),
ClientEvent::Throttle3Set { value } => (ClientEventRequest::Throttle3Set, value),
ClientEvent::Throttle4Set { value } => (ClientEventRequest::Throttle4Set, value),
// Aircraft Flight Controls
ClientEvent::AxisElevatorSet { value } => (ClientEventRequest::AxisElevatorSet, value),
// Aircraft Miscellaneous Systems
ClientEvent::Brakes => (ClientEventRequest::Brakes, 0),
ClientEvent::BrakesLeft => (ClientEventRequest::BrakesLeft, 0),
ClientEvent::BrakesRight => (ClientEventRequest::BrakesRight, 0),
ClientEvent::AxisLeftBrakeSet { value } => {
(ClientEventRequest::AxisLeftBrakeSet, value)
}
ClientEvent::AxisRightBrakeSet { value } => {
(ClientEventRequest::AxisRightBrakeSet, value)
}
ClientEvent::ParkingBrakes => (ClientEventRequest::ParkingBrakes, 0),
}
}
}

View File

@@ -44,8 +44,10 @@ impl FacilityType {
/// Information on a single airport in the facilities cache. /// Information on a single airport in the facilities cache.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Airport { pub struct Airport {
/// ICAO of the facility. /// Ident of the facility.
pub icao: String, pub ident: String,
/// Region of the facility.
pub region: String,
/// Latitude of the airport in facility. /// Latitude of the airport in facility.
pub lat: f64, pub lat: f64,
/// Longitude of the airport in facility. /// Longitude of the airport in facility.
@@ -57,8 +59,10 @@ pub struct Airport {
/// Information on a single waypoint in the facilities cache. /// Information on a single waypoint in the facilities cache.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Waypoint { pub struct Waypoint {
/// ICAO of the facility. /// Ident of the facility.
pub icao: String, pub ident: String,
/// Region of the facility.
pub region: String,
/// Latitude of the airport in facility. /// Latitude of the airport in facility.
pub lat: f64, pub lat: f64,
/// Longitude of the airport in facility. /// Longitude of the airport in facility.
@@ -72,8 +76,10 @@ pub struct Waypoint {
/// Information on a single NDB station in the facilities cache. /// Information on a single NDB station in the facilities cache.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct NDB { pub struct NDB {
/// ICAO of the facility. /// Ident of the facility.
pub icao: String, pub ident: String,
/// Region of the facility.
pub region: String,
/// Latitude of the airport in facility. /// Latitude of the airport in facility.
pub lat: f64, pub lat: f64,
/// Longitude of the airport in facility. /// Longitude of the airport in facility.
@@ -89,8 +95,10 @@ pub struct NDB {
/// Information on a single VOR station in the facilities cache. /// Information on a single VOR station in the facilities cache.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VOR { pub struct VOR {
/// ICAO of the facility. /// Ident of the facility.
pub icao: String, pub ident: String,
/// Region of the facility.
pub region: String,
/// Latitude of the airport in facility. /// Latitude of the airport in facility.
pub lat: f64, pub lat: f64,
/// Longitude of the airport in facility. /// Longitude of the airport in facility.

View File

@@ -1,15 +1,15 @@
mod client_event;
mod condition; mod condition;
mod data_type; mod data_type;
mod events;
mod facilities; mod facilities;
mod notification; mod notification;
mod notification_group;
mod period; mod period;
mod system_event;
pub use client_event::*;
pub use condition::*; pub use condition::*;
pub use data_type::*; pub use data_type::*;
pub use events::*;
pub use facilities::*; pub use facilities::*;
pub use notification::*; pub use notification::*;
pub use notification_group::*;
pub use period::*; pub use period::*;
pub use system_event::*;

View File

@@ -1,6 +0,0 @@
/// SimConnect event notification group.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum NotificationGroup {
Group0,
}

View File

@@ -268,38 +268,3 @@ impl TryFrom<&bindings::SIMCONNECT_RECV_EVENT_FRAME> for SystemEvent {
} }
} }
} }
pub(crate) const CLIENT_EVENT_START: u32 = 128;
/// SimConnect Client Event.
///
/// WIP. As defined by <https://www.prepar3d.com/SDKv5/sdk/references/variables/event_ids.html>.
#[derive(Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive)]
#[repr(u32)]
#[non_exhaustive]
pub enum ClientEvent {
// Aircraft Engine
/// Set throttles max.
ThrottleFull = CLIENT_EVENT_START,
// ---------------
// Aircraft Miscellaneous Systems
/// Increment brake pressure. Note: These are simulated spring-loaded toe brakes, which will bleed back to zero over time.
Brakes,
/// Increments left brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
BrakesLeft,
/// Sets left brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
AxisLeftBrakeSet,
}
impl ClientEvent {
pub(crate) fn into_c_char(self) -> *const c_char {
match self {
// Aircraft Engine
ClientEvent::ThrottleFull => "THROTTLE_FULL\0".as_ptr() as *const c_char,
// Aircraft Miscellaneous Systems
ClientEvent::Brakes => "BRAKES\0".as_ptr() as *const c_char,
ClientEvent::BrakesLeft => "BRAKES_LEFT\0".as_ptr() as *const c_char,
ClientEvent::AxisLeftBrakeSet => "AXIS_LEFT_BRAKE_SET\0".as_ptr() as *const c_char,
}
}
}

View File

@@ -13,15 +13,19 @@ pub enum SimConnectError {
/// An unimplemented event type has been received by the SDK. /// An unimplemented event type has been received by the SDK.
#[error("Unimplemented event in the SDK: {0}")] #[error("Unimplemented event in the SDK: {0}")]
UnimplementedEventType(u32), UnimplementedEventType(u32),
/// An unimplemented message type has been received by the SDK. /// An unimplemented notification has been received by the SDK.
#[error("Unimplemented notification in the SDK: {0}")] #[error("Unimplemented notification in the SDK: {0}")]
UnimplementedMessageType(i32), UnimplementedNotification(i32),
/// Object already registered with the client instance. /// Object already registered with the client instance.
#[error("Object `{0}` has already been registered")] #[error("Object `{0}` has already been registered")]
ObjectAlreadyRegistered(String), ObjectAlreadyRegistered(String),
/// Object already registered with the client instance. /// Object already registered with the client instance.
#[error("Object `{0}` has not been registered")] #[error("Object `{0}` has not been registered")]
ObjectNotRegistered(String), ObjectNotRegistered(String),
#[error("Event `{0}` has already been subscribed to")]
EventAlreadySubscribedTo(String),
#[error("Event `{0}` has not been subscribed to")]
EventNotSubscribedTo(String),
/// Object mismatch. /// Object mismatch.
#[error("Tried to convert object of type {actual} to {expected}")] #[error("Tried to convert object of type {actual} to {expected}")]
ObjectMismatch { actual: String, expected: String }, ObjectMismatch { actual: String, expected: String },

View File

@@ -2,11 +2,13 @@ use std::{collections::HashMap, ffi::c_void};
use tracing::{error, span, trace, warn, Level}; use tracing::{error, span, trace, warn, Level};
use crate::{ use crate::domain::{
as_c_string, bindings, helpers::fixed_c_str_to_string, ok_if_fail, success, Airport, Airport, ClientEvent, ClientEventRequest, Notification, Object, SystemEvent,
ClientEvent, Notification, Object, SimConnectError, SystemEvent, Waypoint, CLIENT_EVENT_START, SystemEventRequest, Waypoint, CLIENT_EVENT_DISCRIMINANT_START, NDB, VOR,
NDB, VOR,
}; };
use crate::helpers::fixed_c_str_to_string;
use crate::simconnect::EventRegister;
use crate::{as_c_string, bindings, ok_if_fail, success, SimConnectError};
/// SimConnect SDK Client. /// SimConnect SDK Client.
/// ///
@@ -83,9 +85,24 @@ use crate::{
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
pub struct SimConnect { pub struct SimConnect {
pub(super) handle: std::ptr::NonNull<c_void>, pub(crate) handle: std::ptr::NonNull<c_void>,
pub(super) next_request_id: u32, pub(crate) next_request_id: u32,
pub(super) registered_objects: HashMap<String, u32>, pub(crate) registered_objects: HashMap<String, RegisteredObject>,
pub(crate) system_event_register: EventRegister<SystemEventRequest>,
pub(crate) client_event_register: EventRegister<ClientEventRequest>,
}
/// A struct that represents a registered object.
#[derive(Debug)]
pub(crate) struct RegisteredObject {
pub id: u32,
pub transient: bool,
}
impl RegisteredObject {
pub(crate) fn new(id: u32, transient: bool) -> Self {
Self { id, transient }
}
} }
impl SimConnect { impl SimConnect {
@@ -113,6 +130,8 @@ impl SimConnect {
})?, })?,
next_request_id: 0, next_request_id: 0,
registered_objects: HashMap::new(), registered_objects: HashMap::new(),
system_event_register: EventRegister::new(),
client_event_register: EventRegister::new(),
}) })
} }
@@ -121,7 +140,7 @@ impl SimConnect {
/// # Remarks /// # Remarks
/// This is a non-blocking function. If there are no messages to receive, it will return None immediately. /// This is a non-blocking function. If there are no messages to receive, it will return None immediately.
/// When called in a loop, it is recommended to use a short sleep time. /// When called in a loop, it is recommended to use a short sleep time.
pub fn get_next_dispatch(&self) -> Result<Option<Notification>, SimConnectError> { pub fn get_next_dispatch(&mut self) -> Result<Option<Notification>, SimConnectError> {
let mut data_buf: *mut bindings::SIMCONNECT_RECV = std::ptr::null_mut(); let mut data_buf: *mut bindings::SIMCONNECT_RECV = std::ptr::null_mut();
let mut size_buf: bindings::DWORD = 32; let mut size_buf: bindings::DWORD = 32;
let size_buf_pointer: *mut bindings::DWORD = &mut size_buf; let size_buf_pointer: *mut bindings::DWORD = &mut size_buf;
@@ -159,9 +178,8 @@ impl SimConnect {
let event: &bindings::SIMCONNECT_RECV_EVENT = let event: &bindings::SIMCONNECT_RECV_EVENT =
unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_EVENT) }; unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_EVENT) };
if event.uEventID >= CLIENT_EVENT_START { if event.uEventID >= CLIENT_EVENT_DISCRIMINANT_START {
let event = ClientEvent::try_from(event.uEventID) let event = ClientEvent::try_from(event)?;
.map_err(|_| SimConnectError::UnimplementedEventType(event.uEventID))?;
Ok(Some(Notification::ClientEvent(event))) Ok(Some(Notification::ClientEvent(event)))
} else { } else {
@@ -212,13 +230,20 @@ impl SimConnect {
let event: &bindings::SIMCONNECT_RECV_AIRPORT_LIST = let event: &bindings::SIMCONNECT_RECV_AIRPORT_LIST =
unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_AIRPORT_LIST) }; unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_AIRPORT_LIST) };
self.unregister_potential_transient_request(
event._base.dwEntryNumber,
event._base.dwOutOf,
event._base.dwRequestID,
);
let data = (0..event._base.dwArraySize as usize) let data = (0..event._base.dwArraySize as usize)
.map(|i| { .map(|i| {
// `rgData` is defined as a 1-element array, but it is actually a variable-length array. // `rgData` is defined as a 1-element array, but it is actually a variable-length array.
let record = unsafe { event.rgData.get_unchecked(i) }; let record = unsafe { event.rgData.get_unchecked(i) };
Airport { Airport {
icao: fixed_c_str_to_string(&record.Icao), ident: fixed_c_str_to_string(&record.Ident),
region: fixed_c_str_to_string(&record.Region),
lat: record.Latitude, lat: record.Latitude,
lon: record.Longitude, lon: record.Longitude,
alt: record.Altitude, alt: record.Altitude,
@@ -234,13 +259,20 @@ impl SimConnect {
let event: &bindings::SIMCONNECT_RECV_WAYPOINT_LIST = let event: &bindings::SIMCONNECT_RECV_WAYPOINT_LIST =
unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_WAYPOINT_LIST) }; unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_WAYPOINT_LIST) };
self.unregister_potential_transient_request(
event._base.dwEntryNumber,
event._base.dwOutOf,
event._base.dwRequestID,
);
let data = (0..event._base.dwArraySize as usize) let data = (0..event._base.dwArraySize as usize)
.map(|i| { .map(|i| {
// `rgData` is defined as a 1-element array, but it is actually a variable-length array. // `rgData` is defined as a 1-element array, but it is actually a variable-length array.
let record = unsafe { event.rgData.get_unchecked(i) }; let record = unsafe { event.rgData.get_unchecked(i) };
Waypoint { Waypoint {
icao: fixed_c_str_to_string(&record._base.Icao), ident: fixed_c_str_to_string(&record._base.Ident),
region: fixed_c_str_to_string(&record._base.Region),
lat: record._base.Latitude, lat: record._base.Latitude,
lon: record._base.Longitude, lon: record._base.Longitude,
alt: record._base.Altitude, alt: record._base.Altitude,
@@ -257,13 +289,20 @@ impl SimConnect {
let event: &bindings::SIMCONNECT_RECV_NDB_LIST = let event: &bindings::SIMCONNECT_RECV_NDB_LIST =
unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_NDB_LIST) }; unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_NDB_LIST) };
self.unregister_potential_transient_request(
event._base.dwEntryNumber,
event._base.dwOutOf,
event._base.dwRequestID,
);
let data = (0..event._base.dwArraySize as usize) let data = (0..event._base.dwArraySize as usize)
.map(|i| { .map(|i| {
// `rgData` is defined as a 1-element array, but it is actually a variable-length array. // `rgData` is defined as a 1-element array, but it is actually a variable-length array.
let record = unsafe { event.rgData.get_unchecked(i) }; let record = unsafe { event.rgData.get_unchecked(i) };
NDB { NDB {
icao: fixed_c_str_to_string(&record._base._base.Icao), ident: fixed_c_str_to_string(&record._base._base.Ident),
region: fixed_c_str_to_string(&record._base._base.Region),
lat: record._base._base.Latitude, lat: record._base._base.Latitude,
lon: record._base._base.Longitude, lon: record._base._base.Longitude,
alt: record._base._base.Altitude, alt: record._base._base.Altitude,
@@ -281,6 +320,12 @@ impl SimConnect {
let event: &bindings::SIMCONNECT_RECV_VOR_LIST = let event: &bindings::SIMCONNECT_RECV_VOR_LIST =
unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_VOR_LIST) }; unsafe { &*(data_buf as *const bindings::SIMCONNECT_RECV_VOR_LIST) };
self.unregister_potential_transient_request(
event._base.dwEntryNumber,
event._base.dwOutOf,
event._base.dwRequestID,
);
let data = (0..event._base.dwArraySize as usize) let data = (0..event._base.dwArraySize as usize)
.map(|i| { .map(|i| {
// `rgData` is defined as a 1-element array, but it is actually a variable-length array. // `rgData` is defined as a 1-element array, but it is actually a variable-length array.
@@ -300,7 +345,8 @@ impl SimConnect {
== bindings::SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME; == bindings::SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME;
VOR { VOR {
icao: fixed_c_str_to_string(&record._base._base._base.Icao), ident: fixed_c_str_to_string(&record._base._base._base.Ident),
region: fixed_c_str_to_string(&record._base._base._base.Region),
lat: record._base._base._base.Latitude, lat: record._base._base._base.Latitude,
lon: record._base._base._base.Longitude, lon: record._base._base._base.Longitude,
alt: record._base._base._base.Altitude, alt: record._base._base._base.Altitude,
@@ -356,7 +402,7 @@ impl SimConnect {
bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NULL => Ok(None), bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NULL => Ok(None),
id => { id => {
error!("Received unhandled notification ID: {}", id); error!("Received unhandled notification ID: {}", id);
Err(SimConnectError::UnimplementedMessageType(id)) Err(SimConnectError::UnimplementedNotification(id))
} }
} }
} }
@@ -364,7 +410,11 @@ impl SimConnect {
/// Register a Request ID in the internal state so that the user doesn't have to manually manage Request IDs. /// Register a Request ID in the internal state so that the user doesn't have to manually manage Request IDs.
#[tracing::instrument(name = "SimConnect::new_request_id", level = "trace", skip(self))] #[tracing::instrument(name = "SimConnect::new_request_id", level = "trace", skip(self))]
pub(super) fn new_request_id(&mut self, type_name: String) -> Result<u32, SimConnectError> { pub(crate) fn new_request_id(
&mut self,
type_name: String,
transient: bool,
) -> Result<u32, SimConnectError> {
if self.registered_objects.contains_key(&type_name) { if self.registered_objects.contains_key(&type_name) {
return Err(SimConnectError::ObjectAlreadyRegistered(type_name)); return Err(SimConnectError::ObjectAlreadyRegistered(type_name));
} }
@@ -374,12 +424,17 @@ impl SimConnect {
// when `next_request_id` overflows some ids might still be in use // when `next_request_id` overflows some ids might still be in use
// so we need to find the next available one // so we need to find the next available one
while self.registered_objects.values().any(|id| *id == request_id) { while self
.registered_objects
.values()
.any(|obj| obj.id == request_id)
{
request_id = self.next_request_id; request_id = self.next_request_id;
self.next_request_id += 1; self.next_request_id += 1;
} }
self.registered_objects.insert(type_name, request_id); self.registered_objects
.insert(type_name, RegisteredObject::new(request_id, transient));
Ok(request_id) Ok(request_id)
} }
@@ -390,8 +445,8 @@ impl SimConnect {
level = "trace", level = "trace",
skip(self) skip(self)
)] )]
pub(super) fn unregister_request_id_by_type_name(&mut self, type_name: &str) -> Option<u32> { pub(crate) fn unregister_request_id_by_type_name(&mut self, type_name: &str) -> Option<u32> {
self.registered_objects.remove(type_name) self.registered_objects.remove(type_name).map(|obj| obj.id)
} }
/// Get the Type Name of a Request ID. /// Get the Type Name of a Request ID.
@@ -400,12 +455,54 @@ impl SimConnect {
level = "trace", level = "trace",
skip(self) skip(self)
)] )]
pub(super) fn get_type_name_by_request_id(&self, request_id: u32) -> Option<String> { pub(crate) fn get_type_name_by_request_id(&self, request_id: u32) -> Option<String> {
self.registered_objects self.registered_objects
.iter() .iter()
.find(|(_, v)| **v == request_id) .find(|(_, v)| v.id == request_id)
.map(|(k, _)| k.clone()) .map(|(k, _)| k.clone())
} }
/// Get the Type Name of a Request ID.
#[tracing::instrument(name = "SimConnect::is_transient_request", level = "trace", skip(self))]
pub(crate) fn is_transient_request(&self, request_id: u32) -> Option<bool> {
self.registered_objects
.iter()
.find(|(_, v)| v.id == request_id)
.map(|(_, v)| v.transient)
}
/// Checks if the request is
/// 1) the last entry in the list and
/// 2) transient
/// and if yes, it gets unregistered.
#[tracing::instrument(
name = "SimConnect::unregister_potential_transient_request",
level = "trace",
fields(type_name, transient),
skip(self)
)]
pub(crate) fn unregister_potential_transient_request(
&mut self,
entry_number: u32,
out_of: u32,
request_id: u32,
) {
if entry_number + 1 >= out_of {
// This is the last entry, so we can clear the request if it's transient.
let transient = self.is_transient_request(request_id);
tracing::Span::current().record("transient", transient);
if self.is_transient_request(request_id) == Some(true) {
let type_name = self.get_type_name_by_request_id(request_id);
if let Some(ref type_name) = type_name {
tracing::Span::current().record("type_name", type_name);
trace!("Clearing");
self.unregister_request_id_by_type_name(type_name);
}
}
}
}
} }
impl Drop for SimConnect { impl Drop for SimConnect {

View File

@@ -0,0 +1,48 @@
use crate::SimConnectError;
#[derive(Debug)]
pub(crate) struct EventRegister<T>
where
T: std::fmt::Debug + std::cmp::PartialEq,
{
items: Vec<T>,
}
impl<T> EventRegister<T>
where
T: std::fmt::Debug + std::cmp::PartialEq,
{
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn is_registered(&self, item: T) -> bool {
self.items.contains(&item)
}
pub fn register(&mut self, item: T) -> Result<(), SimConnectError> {
if self.items.contains(&item) {
return Err(SimConnectError::EventAlreadySubscribedTo(format!(
"{item:?}"
)));
}
self.items.push(item);
Ok(())
}
pub fn unregister(&mut self, item: T) -> Result<(), SimConnectError> {
if !self.items.contains(&item) {
return Err(SimConnectError::EventNotSubscribedTo(format!("{item:?}")));
}
self.items.retain(|i| *i != item);
Ok(())
}
pub fn clear(&mut self) {
self.items.clear();
}
}

View File

@@ -1,18 +1,68 @@
use crate::{ use crate::{
bindings, success, ClientEvent, NotificationGroup, SimConnect, SimConnectError, bindings, success, ClientEventRequest, SimConnect, SimConnectError, SystemEventRequest,
SystemEventRequest,
}; };
// In order to simplify the usage we're using a single notification group for all client events.
const NOTIFICATION_GROUP_ID: u32 = 0;
impl SimConnect { impl SimConnect {
/// Associates a client defined event with a Microsoft Flight Simulator event name. /// Request that a specific system event is notified.
/// #[tracing::instrument(
/// WIP name = "SimConnect::subscribe_to_system_event",
#[tracing::instrument(name = "SimConnect::register_event", level = "debug", skip(self))] level = "debug",
pub fn register_event( skip(self)
&self, )]
event: ClientEvent, pub fn subscribe_to_system_event(
notification_group: NotificationGroup, &mut self,
event: SystemEventRequest,
) -> Result<(), SimConnectError> { ) -> Result<(), SimConnectError> {
self.system_event_register.register(event)?;
success!(unsafe {
bindings::SimConnect_SubscribeToSystemEvent(
self.handle.as_ptr(),
event as u32,
event.into_c_char(),
)
})?;
Ok(())
}
/// Request that notifications are no longer received for the specified system event.
/// If the system event is not subscribed to, this function does nothing.
#[tracing::instrument(
name = "SimConnect::unsubscribe_from_system_event",
level = "debug",
skip(self)
)]
pub fn unsubscribe_from_system_event(
&mut self,
event: SystemEventRequest,
) -> Result<(), SimConnectError> {
if self.system_event_register.is_registered(event) {
success!(unsafe {
bindings::SimConnect_UnsubscribeFromSystemEvent(self.handle.as_ptr(), event as u32)
})?;
self.system_event_register.clear();
}
Ok(())
}
/// Request that a specific client event is notified.
#[tracing::instrument(
name = "SimConnect::subscribe_to_client_event",
level = "debug",
skip(self)
)]
pub fn subscribe_to_client_event(
&mut self,
event: ClientEventRequest,
) -> Result<(), SimConnectError> {
self.client_event_register.register(event)?;
success!(unsafe { success!(unsafe {
bindings::SimConnect_MapClientEventToSimEvent( bindings::SimConnect_MapClientEventToSimEvent(
self.handle.as_ptr(), self.handle.as_ptr(),
@@ -24,7 +74,7 @@ impl SimConnect {
success!(unsafe { success!(unsafe {
bindings::SimConnect_AddClientEventToNotificationGroup( bindings::SimConnect_AddClientEventToNotificationGroup(
self.handle.as_ptr(), self.handle.as_ptr(),
notification_group as u32, NOTIFICATION_GROUP_ID,
event as u32, event as u32,
0, 0,
) )
@@ -33,43 +83,53 @@ impl SimConnect {
success!(unsafe { success!(unsafe {
bindings::SimConnect_SetNotificationGroupPriority( bindings::SimConnect_SetNotificationGroupPriority(
self.handle.as_ptr(), self.handle.as_ptr(),
notification_group as u32, NOTIFICATION_GROUP_ID,
1, bindings::SIMCONNECT_GROUP_PRIORITY_HIGHEST,
) )
}) })?;
Ok(())
} }
/// Request that a specific system event is notified to the client. /// Request that notifications are no longer received for the specified client event.
/// If the client event is not subscribed to, this function does nothing.
#[tracing::instrument( #[tracing::instrument(
name = "SimConnect::subscribe_to_system_event", name = "SimConnect::unsubscribe_from_client_event",
level = "debug", level = "debug",
skip(self) skip(self)
)] )]
pub fn subscribe_to_system_event( pub fn unsubscribe_from_client_event(
&mut self, &mut self,
event: SystemEventRequest, event: ClientEventRequest,
) -> Result<(), SimConnectError> { ) -> Result<(), SimConnectError> {
success!(unsafe { if self.client_event_register.is_registered(event) {
bindings::SimConnect_SubscribeToSystemEvent( success!(unsafe {
self.handle.as_ptr(), bindings::SimConnect_RemoveClientEvent(
event as u32, self.handle.as_ptr(),
event.into_c_char(), NOTIFICATION_GROUP_ID,
) event as u32,
}) )
})?;
self.client_event_register.unregister(event)?;
}
Ok(())
} }
/// Request that notifications are no longer received for the specified system event. /// Request that notifications are no longer received for any client event.
#[tracing::instrument( #[tracing::instrument(
name = "SimConnect::unsubscribe_from_system_event", name = "SimConnect::unsubscribe_from_all_client_events",
level = "debug", level = "debug",
skip(self) skip(self)
)] )]
pub fn unsubscribe_from_system_event( pub fn unsubscribe_from_all_client_events(&mut self) -> Result<(), SimConnectError> {
&mut self,
event: SystemEventRequest,
) -> Result<(), SimConnectError> {
success!(unsafe { success!(unsafe {
bindings::SimConnect_UnsubscribeFromSystemEvent(self.handle.as_ptr(), event as u32) bindings::SimConnect_ClearNotificationGroup(self.handle.as_ptr(), NOTIFICATION_GROUP_ID)
}) })?;
self.client_event_register.clear();
Ok(())
} }
} }

View File

@@ -4,7 +4,7 @@ impl SimConnect {
/// Request a list of all the facilities of a given type currently held in the facilities cache. /// Request a list of all the facilities of a given type currently held in the facilities cache.
/// ///
/// # Errors /// # Errors
/// - [`crate::SimConnectError::ObjectAlreadyRegistered`] -- Only one request or subscription per facility type is allowed. If you wish to create a new one, unsubscribe first using [`crate::SimConnect::unsubscribe_to_facilities`]. /// - [`crate::SimConnectError::ObjectAlreadyRegistered`] -- Only one request per facility type is supported.
/// ///
/// # Remarks /// # Remarks
/// The simulation keeps a facilities cache of all the airports, waypoints, NDB and VOR stations within a certain radius of the user aircraft. /// The simulation keeps a facilities cache of all the airports, waypoints, NDB and VOR stations within a certain radius of the user aircraft.
@@ -20,7 +20,7 @@ impl SimConnect {
facility_type: FacilityType, facility_type: FacilityType,
) -> Result<(), SimConnectError> { ) -> Result<(), SimConnectError> {
let type_name = facility_type.to_type_name(); let type_name = facility_type.to_type_name();
let request_id = self.new_request_id(type_name)?; let request_id = self.new_request_id(type_name, true)?;
success!(unsafe { success!(unsafe {
bindings::SimConnect_RequestFacilitiesList( bindings::SimConnect_RequestFacilitiesList(
@@ -38,7 +38,7 @@ impl SimConnect {
/// To terminate these notifications use the [`crate::SimConnect::unsubscribe_to_facilities`] function. /// To terminate these notifications use the [`crate::SimConnect::unsubscribe_to_facilities`] function.
/// ///
/// # Errors /// # Errors
/// - [`crate::SimConnectError::ObjectAlreadyRegistered`] -- Only one subscription or request per facility type is allowed. If you wish to create a new one, unsubscribe first using [`crate::SimConnect::unsubscribe_to_facilities`]. /// - [`crate::SimConnectError::ObjectAlreadyRegistered`] -- Only one subscription per facility type is supported. If you wish to create a new one, unsubscribe first using [`crate::SimConnect::unsubscribe_to_facilities`].
/// ///
/// # Remarks /// # Remarks
/// The simulation keeps a facilities cache of all the airports, waypoints, NDB and VOR stations within a certain radius of the user aircraft. /// The simulation keeps a facilities cache of all the airports, waypoints, NDB and VOR stations within a certain radius of the user aircraft.
@@ -54,7 +54,7 @@ impl SimConnect {
facility_type: FacilityType, facility_type: FacilityType,
) -> Result<(), SimConnectError> { ) -> Result<(), SimConnectError> {
let type_name = facility_type.to_type_name(); let type_name = facility_type.to_type_name();
let request_id = self.new_request_id(type_name)?; let request_id = self.new_request_id(type_name, false)?;
success!(unsafe { success!(unsafe {
bindings::SimConnect_SubscribeToFacilities( bindings::SimConnect_SubscribeToFacilities(
@@ -68,7 +68,7 @@ impl SimConnect {
/// Request that notifications of additions to the facilities cache are not longer sent. /// Request that notifications of additions to the facilities cache are not longer sent.
/// ///
/// # Remarks /// # Remarks
/// This is used to terminate notifications generated by the [`crate::SimConnect::request_facilities_list`] or [`crate::SimConnect::subscribe_to_facilities`] functions. /// This is used to terminate notifications generated by the [`crate::SimConnect::subscribe_to_facilities`] function.
#[tracing::instrument( #[tracing::instrument(
name = "SimConnect::unsubscribe_to_facilities", name = "SimConnect::unsubscribe_to_facilities",
level = "debug", level = "debug",

View File

@@ -1,8 +1,11 @@
mod base; mod base;
mod event_register;
mod events; mod events;
mod facilities; mod facilities;
mod objects; mod objects;
pub(crate) use event_register::*;
pub use base::*; pub use base::*;
pub use events::*; pub use events::*;
pub use facilities::*; pub use facilities::*;

View File

@@ -9,7 +9,7 @@ impl SimConnect {
pub fn register_object<T: SimConnectObjectExt>(&mut self) -> Result<u32, SimConnectError> { pub fn register_object<T: SimConnectObjectExt>(&mut self) -> Result<u32, SimConnectError> {
let type_name: String = std::any::type_name::<T>().into(); let type_name: String = std::any::type_name::<T>().into();
let id = self.new_request_id(type_name)?; let id = self.new_request_id(type_name, false)?;
T::register(self, id)?; T::register(self, id)?;
@@ -27,7 +27,7 @@ impl SimConnect {
.ok_or_else(|| SimConnectError::ObjectNotRegistered(type_name.clone()))?; .ok_or_else(|| SimConnectError::ObjectNotRegistered(type_name.clone()))?;
success!(unsafe { success!(unsafe {
bindings::SimConnect_ClearDataDefinition(self.handle.as_ptr(), *request_id) bindings::SimConnect_ClearDataDefinition(self.handle.as_ptr(), request_id.id)
})?; })?;
self.unregister_request_id_by_type_name(&type_name) self.unregister_request_id_by_type_name(&type_name)