pfly_rust/
lib.rs

1//! pfly_rust is a crate to interact with the projectFly X-Plane IPC service.
2//!
3//! This was originally made to create a Linux supported alternative to the native X-Plane projectFly plugin, which is from a project to port projectFly over to Linux.
4//!
5//! Creating a connection is super easy, calling [`init`] will give you a socket object that is bonded and connected to projectFly.
6//! You can then use [`send_message`] to send a message to projectFly with the structure of [`PflyIpcData`].
7//!
8//! [`init`]: fn.init.html
9//! [`send_message`]: fn.send_message.html
10//! [`PflyIpcData`]: struct.PflyIpcData.html
11
12use serde::Serialize;
13use socket2::{Domain, SockAddr, Socket, Type};
14
15/// Connects to the projectFly Unix socket at `/tmp/pf.sock`.
16///
17/// Returns said socket for future use.
18///
19/// # Example
20///
21/// ```
22/// let pfly_socket = pfly_rust::init();
23/// ```
24pub fn init() -> Socket {
25    let pfly_socket = Socket::new(Domain::unix(), Type::stream(), None).unwrap();
26    let pfly_socket_addr = &SockAddr::unix("/tmp/pf.sock").unwrap();
27
28    if pfly_socket.connect(pfly_socket_addr).is_err() {
29        panic!("Could not connect to projectFly socket!")
30    }
31
32    return pfly_socket;
33}
34
35/// Sends a message to the projectFly socket with a [`PflyIpcData`] payload converted into u8.
36///
37/// Returns false if any errors ocurred when sending
38///
39/// # Arguments
40/// * `pfly_socket` - The socket object from init()
41/// * `data` - Information to be sent in the form of [`PflyIpcData`]
42///
43/// # Example
44///
45/// ```
46/// let pfly_socket = pfly_rust::init();
47///
48/// pfly_rust::send_message(pfly_socket, pfly_rust::PflyIpcData{
49///     altitude: 569,
50///     agl: 0,
51///     groundspeed: 0,
52///     ias: 0,
53///     headingTrue: 0,
54///     headingMagnetic: 0,
55///     latitude: 43.6772222,
56///     longitude: -79.6305556,
57///     verticalSpeed: 0,
58///     landingVerticalSpeed: 0,
59///     gForce: 1000, // Divided by 1000 by projectFly
60///     fuel: 20000,
61///     transponder: 1425,
62///     bridgeType: 3, // From projectFly: bridgeTypes = ['simconnect', 'fsuipc', 'if', 'xplane']
63///     isOnGround: true,
64///     isSlew: false,
65///     isPaused: false,
66///     pitch: 0,
67///     roll: 0,
68///     time: 0, // This is calculated by projectFly
69///     fps: 120,
70///     aircraftType: "B77W" // Unused by projectFly, still required just in case
71/// });
72/// ```
73///
74/// [`PflyIpcData`]: struct.PflyIpcData.html
75pub fn send_message(pfly_socket: Socket, data: PflyIpcData) -> bool {
76    let payload: Vec<u8> = bincode::serialize(&data).unwrap();
77
78    return pfly_socket.send(payload.as_ref()).is_ok();
79}
80
81/// Structure of data that projectFly expects over it's X-Plane IPC connection.
82///
83/// As found in `/src/app/providers/flightsim.service.ts` of the projectFly source.
84#[allow(non_snake_case)]
85#[derive(Serialize)]
86pub struct PflyIpcData {
87    pub altitude: i32,
88    pub agl: i32,
89    pub groundspeed: i32,
90    pub ias: i32,
91    pub headingTrue: i32,
92    pub headingMagnetic: i32,
93    pub latitude: f64,
94    pub longitude: f64,
95    pub verticalSpeed: i32,
96    pub landingVerticalSpeed: i32,
97    pub gForce: i32,
98    pub fuel: i32,
99    pub transponder: i32,
100    pub bridgeType: u8,
101    pub isOnGround: bool,
102    pub isSlew: bool,
103    pub isPaused: bool,
104    pub pitch: i32,
105    pub roll: i32,
106    pub time: i32, // This is calculated at projectFly
107    pub fps: i32,
108    pub aircraftType: &'static str, // This isn't applied on the projectFly side for some reason, still adding it just incase
109}