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}