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
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! Telemetry client for F1 game by Codemasters
//!
//! # Example
//!
//! ```rust
//! use f1_telemetry_client::{Telemetry, packet::Packet};
//! use async_std::task;
//!
//! fn main() {
//!     task::block_on(async {
//!         let telemetry = Telemetry::new("127.0.0.1", 20777).await.unwrap();
//!
//!         loop {
//!             match telemetry.next().await {
//!                 Ok(packet) => {
//!                     match packet {
//!                         Packet::F12020(result) => {
//!                             println!("Result {:?}", result);
//!                         }
//!                         _ => unimplemented!(),
//!                     }
//!                 }
//!                 Err(e) => {
//!                     eprintln!("Error {}", e)
//!                 }
//!             }
//!         }
//!     })
//! }
//! ```

use async_std::io::{Cursor, Error};
use async_std::net::{IpAddr, SocketAddr, UdpSocket};

use byteorder_async::{LittleEndian, ReaderToByteOrder};
use std::str::FromStr;

pub mod f1_2020;
pub mod packet;

pub struct Telemetry(UdpSocket);

impl Telemetry {
    pub async fn new(ip: &str, port: u16) -> Result<Self, Error> {
        let ip = IpAddr::from_str(ip).expect("Invalid ip address");
        let socket_addrs = SocketAddr::new(ip, port);
        let socket = UdpSocket::bind(socket_addrs).await?;

        Ok(Telemetry(socket))
    }

    pub async fn next(&self) -> Result<packet::Packet, Error> {
        let mut buf = vec![0; 2048];
        let (size, _) = self.0.recv_from(&mut buf).await?;
        let mut cursor = Cursor::new(buf);

        let packet_format = cursor
            .clone()
            .byte_order()
            .read_u16::<LittleEndian>()
            .await?;
        match packet_format {
            2020 => {
                let result = f1_2020::packet::parse_f12020(&mut cursor, size).await?;
                Ok(packet::Packet::F12020(result))
            }
            2019 => unimplemented!(),
            2018 => unimplemented!(),
            _ => unimplemented!(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use async_std::net::UdpSocket;
    use async_std::task::spawn;
    use byteorder_async::WriteBytesExt;

    fn send() {
        let handle = spawn(async {
            let socket = UdpSocket::bind("127.0.0.1:8080").await.unwrap();
            let mut send_buf = Vec::with_capacity(2048);
            send_buf.write_u16::<LittleEndian>(2020).unwrap();
            send_buf.write_u8(1).unwrap();
            send_buf.write_u8(2).unwrap();
            send_buf.write_u8(3).unwrap();
            send_buf.write_u8(0).unwrap();
            send_buf
                .write_u64::<LittleEndian>(u64::max_value())
                .unwrap();
            send_buf.write_f32::<LittleEndian>(1.0).unwrap();
            send_buf
                .write_u32::<LittleEndian>(u32::max_value())
                .unwrap();
            send_buf.write_u8(19).unwrap();
            send_buf.write_u8(255).unwrap();
            socket.send_to(&*send_buf, "127.0.0.1:20777").await.unwrap();
        });

        drop(handle);
    }

    #[async_std::test]
    async fn test_telemetry_next() {
        send();

        let client = Telemetry::new("127.0.0.1", 20777).await.unwrap();
        let result = client.next().await.map_err(|e| e.kind());
        assert_eq!(result, Err(async_std::io::ErrorKind::InvalidData));
    }
}