f1_telemetry_client/
lib.rs

1//! Telemetry client for F1 game by Codemasters
2//!
3//! # Example
4//!
5//! ```rust
6//! use f1_telemetry_client::{Telemetry, packet::Packet};
7//! use async_std::task;
8//!
9//! fn main() {
10//!     task::block_on(async {
11//!         let telemetry = Telemetry::new("127.0.0.1", 20777).await.unwrap();
12//!
13//!         loop {
14//!             match telemetry.next().await {
15//!                 Ok(packet) => {
16//!                     match packet {
17//!                         Packet::F12020(result) => {
18//!                             println!("Result {:?}", result);
19//!                         }
20//!                         _ => unimplemented!(),
21//!                     }
22//!                 }
23//!                 Err(e) => {
24//!                     eprintln!("Error {}", e)
25//!                 }
26//!             }
27//!         }
28//!     })
29//! }
30//! ```
31
32use async_std::io::{Cursor, Error};
33use async_std::net::{IpAddr, SocketAddr, UdpSocket};
34
35use byteorder_async::{LittleEndian, ReaderToByteOrder};
36use std::str::FromStr;
37
38pub mod f1_2020;
39pub mod packet;
40
41pub struct Telemetry(UdpSocket);
42
43impl Telemetry {
44    pub async fn new(ip: &str, port: u16) -> Result<Self, Error> {
45        let ip = IpAddr::from_str(ip).expect("Invalid ip address");
46        let socket_addrs = SocketAddr::new(ip, port);
47        let socket = UdpSocket::bind(socket_addrs).await?;
48
49        Ok(Telemetry(socket))
50    }
51
52    pub async fn next(&self) -> Result<packet::Packet, Error> {
53        let mut buf = vec![0; 2048];
54        let (size, _) = self.0.recv_from(&mut buf).await?;
55        let mut cursor = Cursor::new(buf);
56
57        let packet_format = cursor
58            .clone()
59            .byte_order()
60            .read_u16::<LittleEndian>()
61            .await?;
62        match packet_format {
63            2020 => {
64                let result = f1_2020::packet::parse_f12020(&mut cursor, size).await?;
65                Ok(packet::Packet::F12020(result))
66            }
67            2019 => unimplemented!(),
68            2018 => unimplemented!(),
69            _ => unimplemented!(),
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use async_std::net::UdpSocket;
78    use async_std::task::spawn;
79    use byteorder_async::WriteBytesExt;
80
81    fn send() {
82        let handle = spawn(async {
83            let socket = UdpSocket::bind("127.0.0.1:8080").await.unwrap();
84            let mut send_buf = Vec::with_capacity(2048);
85            send_buf.write_u16::<LittleEndian>(2020).unwrap();
86            send_buf.write_u8(1).unwrap();
87            send_buf.write_u8(2).unwrap();
88            send_buf.write_u8(3).unwrap();
89            send_buf.write_u8(0).unwrap();
90            send_buf
91                .write_u64::<LittleEndian>(u64::max_value())
92                .unwrap();
93            send_buf.write_f32::<LittleEndian>(1.0).unwrap();
94            send_buf
95                .write_u32::<LittleEndian>(u32::max_value())
96                .unwrap();
97            send_buf.write_u8(19).unwrap();
98            send_buf.write_u8(255).unwrap();
99            socket.send_to(&*send_buf, "127.0.0.1:20777").await.unwrap();
100        });
101
102        drop(handle);
103    }
104
105    #[async_std::test]
106    async fn test_telemetry_next() {
107        send();
108
109        let client = Telemetry::new("127.0.0.1", 20777).await.unwrap();
110        let result = client.next().await.map_err(|e| e.kind());
111        assert_eq!(result, Err(async_std::io::ErrorKind::InvalidData));
112    }
113}