1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
//! A Rust implementation of the telemetry API provided by modern F1 video games use crate::codec::F1Codec; use crate::packet::Packet; use net2::UdpBuilder; use std::io::Error; use std::net::SocketAddr; use tokio::net::UdpSocket; use tokio::stream::{Stream, StreamExt}; use tokio_util::udp::UdpFramed; pub mod codec; pub mod nineteen; pub mod packet; pub mod types; /// A high-level interface to the telemetry data of modern F1 video games. /// /// The F1 struct implements a high-level interface to the telemetry data of the /// modern F1 video games. It is the recommended way to use the library, as it /// provides a simple interface to consumers that hides the low-level internals /// of the library. pub struct F1 {} impl F1 { /// Create a stream that yields decoded UDP packets. /// /// Modern F1 games publish their telemetry and session data through a UDP-based protocol. With /// this function, a stream can be created that listens at the given socket for incoming /// packets, decodes them using the `F1Codec`, and returns their Rust representations. /// /// # Examples /// /// ``` /// use f1_api::F1; /// use f1_api::packet::Packet::{Event, Lap, Motion, Participants, Session, Setup, Status, Telemetry}; /// use std::net::{IpAddr, SocketAddr}; /// use tokio::stream::StreamExt; /// /// async fn example() { /// let ip_address = IpAddr::from([0, 0, 0, 0]); /// let port = 20777; /// let socket = SocketAddr::new(ip_address, port); /// /// let mut stream = F1::stream(socket).unwrap(); /// /// while let Some(packet) = stream.next().await { /// match packet { /// Event(_) => println!("Received Event packet"), /// Lap(_) => println!("Received Lap packet"), /// Motion(_) => println!("Received Motion packet"), /// Participants(_) => println!("Received Participants packet"), /// Session(_) => println!("Received Session packet"), /// Setup(_) => println!("Received Setup packet"), /// Status(_) => println!("Received Status packet"), /// Telemetry(_) => println!("Received Telemetry packet"), /// } /// } /// } /// ``` pub fn stream(socket_address: SocketAddr) -> Result<impl Stream<Item = Packet>, Error> { let socket = match socket_address { SocketAddr::V4(address) => UdpBuilder::new_v4()?.bind(address), SocketAddr::V6(address) => UdpBuilder::new_v6()?.only_v6(true)?.bind(address), }?; Ok(UdpFramed::new(UdpSocket::from_std(socket)?, F1Codec) .map(|result| result.unwrap()) .map(|(packet, _address)| packet)) } }