Skip to main content

simconnect_sdk/domain/
client_event.rs

1use std::os::raw::c_char;
2
3use crate::{bindings, SimConnectError};
4
5// System Events start from 0 so we have to stagger the values to avoid collisions.
6pub(crate) const CLIENT_EVENT_DISCRIMINANT_START: u32 = 1024;
7
8/// SimConnect Client Event Request.
9///
10/// Defined by <https://www.prepar3d.com/SDKv5/sdk/references/variables/event_ids.html>.
11/// Extended by <https://docs.flightsimulator.com/html/Programming_Tools/Event_IDs/Event_IDs.htm>.
12#[derive(Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive)]
13#[repr(u32)]
14#[non_exhaustive]
15pub enum ClientEventRequest {
16    // ---------------
17    // Aircraft Engine
18    // ---------------
19    /// Set throttle 1 exactly (0 to 16383).
20    Throttle1Set = CLIENT_EVENT_DISCRIMINANT_START,
21    /// Set throttle 2 exactly (0 to 16383).
22    Throttle2Set,
23    /// Set throttle 3 exactly (0 to 16383).
24    Throttle3Set,
25    /// Set throttle 4 exactly (0 to 16383).
26    Throttle4Set,
27    // ---------------
28    // Aircraft Flight Controls
29    // ---------------
30    /// Sets elevator position (-16383 - +16383).
31    AxisElevatorSet,
32    // ---------------
33    // Aircraft Miscellaneous Systems
34    // ---------------
35    /// Increment brake pressure. Note: These are simulated spring-loaded toe brakes, which will bleed back to zero over time.
36    Brakes,
37    /// Increments left brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
38    BrakesLeft,
39    /// Increments right brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
40    BrakesRight,
41    /// Sets left brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
42    AxisLeftBrakeSet,
43    /// Sets right brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
44    AxisRightBrakeSet,
45    /// Toggles parking brake on/off.
46    ParkingBrakes,
47}
48
49impl ClientEventRequest {
50    pub(crate) fn into_c_char(self) -> *const c_char {
51        match self {
52            // Aircraft Engine
53            Self::Throttle1Set => c"THROTTLE1_SET".as_ptr() as *const c_char,
54            Self::Throttle2Set => c"THROTTLE2_SET".as_ptr() as *const c_char,
55            Self::Throttle3Set => c"THROTTLE3_SET".as_ptr() as *const c_char,
56            Self::Throttle4Set => c"THROTTLE4_SET".as_ptr() as *const c_char,
57            // Aircraft Flight Controls
58            Self::AxisElevatorSet => c"AXIS_ELEVATOR_SET".as_ptr() as *const c_char,
59            // Aircraft Miscellaneous Systems
60            Self::Brakes => c"BRAKES".as_ptr() as *const c_char,
61            Self::BrakesLeft => c"BRAKES_LEFT".as_ptr() as *const c_char,
62            Self::BrakesRight => c"BRAKES_RIGHT".as_ptr() as *const c_char,
63            Self::AxisLeftBrakeSet => c"AXIS_LEFT_BRAKE_SET".as_ptr() as *const c_char,
64            Self::AxisRightBrakeSet => c"AXIS_RIGHT_BRAKE_SET".as_ptr() as *const c_char,
65            Self::ParkingBrakes => c"PARKING_BRAKES".as_ptr() as *const c_char,
66        }
67    }
68}
69
70/// SimConnect Client Event.
71///
72/// Defined by <https://www.prepar3d.com/SDKv5/sdk/references/variables/event_ids.html>.
73/// Extended by <https://docs.flightsimulator.com/html/Programming_Tools/Event_IDs/Event_IDs.htm>.
74#[derive(Debug, Copy, Clone, PartialEq, Eq)]
75#[non_exhaustive]
76pub enum ClientEvent {
77    // ---------------
78    // Aircraft Engine
79    // ---------------
80    /// Set throttle 1 exactly (0 to 16383).
81    Throttle1Set {
82        /// -16383 (0 throttle) to +16383 (max throttle).
83        value: i32,
84    },
85    /// Set throttle 2 exactly (0 to 16383).
86    Throttle2Set {
87        /// -16383 (0 throttle) to +16383 (max throttle).
88        value: i32,
89    },
90    /// Set throttle 3 exactly (0 to 16383).
91    Throttle3Set {
92        /// -16383 (0 throttle) to +16383 (max throttle).
93        value: i32,
94    },
95    /// Set throttle 4 exactly (0 to 16383).
96    Throttle4Set {
97        /// -16383 (0 throttle) to +16383 (max throttle).
98        value: i32,
99    },
100    // ---------------
101    // Aircraft Flight Controls
102    // ---------------
103    /// Sets elevator position (-16383 - +16383).
104    AxisElevatorSet {
105        /// -16383 (full down) to +16383 (full up).
106        value: i32,
107    },
108    // ---------------
109    // Aircraft Miscellaneous Systems
110    // ---------------
111    /// Increment brake pressure. Note: These are simulated spring-loaded toe brakes, which will bleed back to zero over time.
112    Brakes,
113    /// Increments left brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
114    BrakesLeft,
115    /// Increments right brake pressure. Note: This is a simulated spring-loaded toe brake, which will bleed back to zero over time.
116    BrakesRight,
117    /// Sets left brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
118    AxisLeftBrakeSet {
119        /// -16383 (0 brakes) to +16383 (max brakes).
120        value: i32,
121    },
122    /// Sets right brake position from axis controller (e.g. joystick). -16383 (0 brakes) to +16383 (max brakes).
123    AxisRightBrakeSet {
124        /// -16383 (0 brakes) to +16383 (max brakes).
125        value: i32,
126    },
127    /// Toggles parking brake on/off.
128    ParkingBrakes,
129}
130
131impl TryFrom<&bindings::SIMCONNECT_RECV_EVENT> for ClientEvent {
132    type Error = SimConnectError;
133
134    fn try_from(event: &bindings::SIMCONNECT_RECV_EVENT) -> Result<Self, Self::Error> {
135        let request = ClientEventRequest::try_from(event.uEventID)
136            .map_err(|_| SimConnectError::UnimplementedEventType(event.uEventID))?;
137
138        match request {
139            // Aircraft Engine
140            ClientEventRequest::Throttle1Set => Ok(Self::Throttle1Set {
141                value: event.dwData as i32,
142            }),
143            ClientEventRequest::Throttle2Set => Ok(Self::Throttle2Set {
144                value: event.dwData as i32,
145            }),
146            ClientEventRequest::Throttle3Set => Ok(Self::Throttle3Set {
147                value: event.dwData as i32,
148            }),
149            ClientEventRequest::Throttle4Set => Ok(Self::Throttle4Set {
150                value: event.dwData as i32,
151            }),
152            // Aircraft Flight Controls
153            ClientEventRequest::AxisElevatorSet => Ok(Self::AxisElevatorSet {
154                value: event.dwData as i32,
155            }),
156            // Aircraft Miscellaneous Systems
157            ClientEventRequest::Brakes => Ok(Self::Brakes),
158            ClientEventRequest::BrakesLeft => Ok(Self::BrakesLeft),
159            ClientEventRequest::BrakesRight => Ok(Self::BrakesRight),
160            ClientEventRequest::AxisLeftBrakeSet => Ok(Self::AxisLeftBrakeSet {
161                value: event.dwData as i32,
162            }),
163            ClientEventRequest::AxisRightBrakeSet => Ok(Self::AxisRightBrakeSet {
164                value: event.dwData as i32,
165            }),
166            ClientEventRequest::ParkingBrakes => Ok(Self::ParkingBrakes),
167        }
168    }
169}
170
171impl From<ClientEvent> for (ClientEventRequest, i32) {
172    fn from(event: ClientEvent) -> Self {
173        match event {
174            // Aircraft Engine
175            ClientEvent::Throttle1Set { value } => (ClientEventRequest::Throttle1Set, value),
176            ClientEvent::Throttle2Set { value } => (ClientEventRequest::Throttle2Set, value),
177            ClientEvent::Throttle3Set { value } => (ClientEventRequest::Throttle3Set, value),
178            ClientEvent::Throttle4Set { value } => (ClientEventRequest::Throttle4Set, value),
179            // Aircraft Flight Controls
180            ClientEvent::AxisElevatorSet { value } => (ClientEventRequest::AxisElevatorSet, value),
181            // Aircraft Miscellaneous Systems
182            ClientEvent::Brakes => (ClientEventRequest::Brakes, 0),
183            ClientEvent::BrakesLeft => (ClientEventRequest::BrakesLeft, 0),
184            ClientEvent::BrakesRight => (ClientEventRequest::BrakesRight, 0),
185            ClientEvent::AxisLeftBrakeSet { value } => {
186                (ClientEventRequest::AxisLeftBrakeSet, value)
187            }
188            ClientEvent::AxisRightBrakeSet { value } => {
189                (ClientEventRequest::AxisRightBrakeSet, value)
190            }
191            ClientEvent::ParkingBrakes => (ClientEventRequest::ParkingBrakes, 0),
192        }
193    }
194}