f1_api/nineteen/
telemetry.rs

1//! Decoder for telemetry packets sent by F1 2019
2//!
3//! The telemetry packets by F1 2018 and F1 2019 differ only in their packet headers, the rest of
4//! the packet format is identical.
5
6use std::io::{Cursor, Error, ErrorKind};
7
8use bytes::{Buf, BytesMut};
9
10use crate::nineteen::header::decode_header;
11use crate::packet::ensure_packet_size;
12use crate::packet::telemetry::{Button, Gear, Surface, Telemetry, TelemetryPacket};
13use crate::types::CornerProperty;
14
15/// Size of the telemetry packet in bytes
16pub const PACKET_SIZE: usize = 1347;
17
18/// Decode a telemetry packet sent by F1 2019
19///
20/// F1 2018 and F1 2019 publish the same data in their telemetry packets, but with different packet
21/// headers.
22pub fn decode_telemetry(cursor: &mut Cursor<&mut BytesMut>) -> Result<TelemetryPacket, Error> {
23    ensure_packet_size(PACKET_SIZE, cursor)?;
24
25    let header = decode_header(cursor)?;
26    let mut telemetry = Vec::with_capacity(20);
27
28    for _ in 0..20 {
29        telemetry.push(Telemetry::new(
30            cursor.get_u16_le(),
31            cursor.get_f32_le(),
32            cursor.get_f32_le(),
33            cursor.get_f32_le(),
34            cursor.get_u8(),
35            decode_gear(cursor)?,
36            cursor.get_u16_le(),
37            cursor.get_u8() > 0,
38            cursor.get_u8(),
39            decode_brake_temperature(cursor),
40            decode_tyre_surface_temperature(cursor),
41            decode_tyre_inner_temperature(cursor),
42            cursor.get_u16_le(),
43            decode_tyre_pressure(cursor),
44            decode_surface_type(cursor)?,
45        ));
46    }
47
48    let button_status = match Button::from_bits(cursor.get_u32_le()) {
49        Some(button) => button,
50        None => Button::NONE,
51    };
52
53    Ok(TelemetryPacket::new(header, telemetry, button_status))
54}
55
56fn decode_gear(cursor: &mut Cursor<&mut BytesMut>) -> Result<Gear, Error> {
57    let value = cursor.get_i8();
58
59    match value {
60        -1 => Ok(Gear::Reverse),
61        0 => Ok(Gear::Neutral),
62        1 => Ok(Gear::First),
63        2 => Ok(Gear::Second),
64        3 => Ok(Gear::Third),
65        4 => Ok(Gear::Fourth),
66        5 => Ok(Gear::Fifth),
67        6 => Ok(Gear::Sixth),
68        7 => Ok(Gear::Seventh),
69        8 => Ok(Gear::Eighth),
70        _ => Err(Error::new(ErrorKind::InvalidData, "Failed to decode gear.")),
71    }
72}
73
74fn decode_brake_temperature(cursor: &mut Cursor<&mut BytesMut>) -> CornerProperty<u16> {
75    CornerProperty::new(
76        cursor.get_u16_le(),
77        cursor.get_u16_le(),
78        cursor.get_u16_le(),
79        cursor.get_u16_le(),
80    )
81}
82
83fn decode_tyre_surface_temperature(cursor: &mut Cursor<&mut BytesMut>) -> CornerProperty<u16> {
84    CornerProperty::new(
85        cursor.get_u16_le(),
86        cursor.get_u16_le(),
87        cursor.get_u16_le(),
88        cursor.get_u16_le(),
89    )
90}
91
92fn decode_tyre_inner_temperature(cursor: &mut Cursor<&mut BytesMut>) -> CornerProperty<u16> {
93    CornerProperty::new(
94        cursor.get_u16_le(),
95        cursor.get_u16_le(),
96        cursor.get_u16_le(),
97        cursor.get_u16_le(),
98    )
99}
100
101fn decode_tyre_pressure(cursor: &mut Cursor<&mut BytesMut>) -> CornerProperty<f32> {
102    CornerProperty::new(
103        cursor.get_f32_le(),
104        cursor.get_f32_le(),
105        cursor.get_f32_le(),
106        cursor.get_f32_le(),
107    )
108}
109
110fn decode_surface_type(
111    cursor: &mut Cursor<&mut BytesMut>,
112) -> Result<CornerProperty<Surface>, Error> {
113    Ok(CornerProperty::new(
114        decode_surface(cursor)?,
115        decode_surface(cursor)?,
116        decode_surface(cursor)?,
117        decode_surface(cursor)?,
118    ))
119}
120
121fn decode_surface(cursor: &mut Cursor<&mut BytesMut>) -> Result<Surface, Error> {
122    let value = cursor.get_u8();
123
124    match value {
125        0 => Ok(Surface::Tarmac),
126        1 => Ok(Surface::RumbleStrip),
127        2 => Ok(Surface::Concrete),
128        3 => Ok(Surface::Rock),
129        4 => Ok(Surface::Gravel),
130        5 => Ok(Surface::Mud),
131        6 => Ok(Surface::Sand),
132        7 => Ok(Surface::Grass),
133        8 => Ok(Surface::Water),
134        9 => Ok(Surface::Cobblestone),
135        10 => Ok(Surface::Metal),
136        11 => Ok(Surface::Ridged),
137        _ => Err(Error::new(
138            ErrorKind::InvalidData,
139            "Failed to decode surface.",
140        )),
141    }
142}
143
144#[cfg(test)]
145mod tests {
146    use std::io::Cursor;
147
148    use assert_approx_eq::assert_approx_eq;
149    use bytes::{BufMut, BytesMut};
150
151    use crate::nineteen::telemetry::{decode_telemetry, PACKET_SIZE};
152    use crate::packet::telemetry::{Button, Gear, Surface};
153
154    fn put_packet_header(mut bytes: BytesMut) -> BytesMut {
155        bytes.put_u16_le(2019);
156        bytes.put_u8(1);
157        bytes.put_u8(2);
158        bytes.put_u8(3);
159        bytes.put_u8(0);
160        bytes.put_u64_le(u64::max_value());
161        bytes.put_f32_le(1.0);
162        bytes.put_u32_le(u32::max_value());
163        bytes.put_u8(0);
164
165        bytes
166    }
167
168    #[test]
169    fn decode_telemetry_with_error() {
170        let mut bytes = BytesMut::with_capacity(0);
171        let mut cursor = Cursor::new(&mut bytes);
172
173        let packet = decode_telemetry(&mut cursor);
174        assert!(packet.is_err());
175    }
176
177    #[test]
178    fn decode_telemetry_with_success() {
179        let mut bytes = BytesMut::with_capacity(PACKET_SIZE);
180        bytes = put_packet_header(bytes);
181
182        for _ in 0..20 {
183            bytes.put_u16_le(1);
184            bytes.put_f32_le(2.0);
185            bytes.put_f32_le(3.0);
186            bytes.put_f32_le(4.0);
187            bytes.put_u8(5);
188            bytes.put_u8(6);
189            bytes.put_u16_le(7);
190            bytes.put_u8(1);
191            bytes.put_u8(9);
192            bytes.put_u16_le(10);
193            bytes.put_u16_le(11);
194            bytes.put_u16_le(12);
195            bytes.put_u16_le(13);
196            bytes.put_u16_le(14);
197            bytes.put_u16_le(15);
198            bytes.put_u16_le(16);
199            bytes.put_u16_le(17);
200            bytes.put_u16_le(18);
201            bytes.put_u16_le(19);
202            bytes.put_u16_le(20);
203            bytes.put_u16_le(21);
204            bytes.put_u16_le(22);
205            bytes.put_f32_le(23.0);
206            bytes.put_f32_le(24.0);
207            bytes.put_f32_le(25.0);
208            bytes.put_f32_le(26.0);
209            bytes.put_u8(5);
210            bytes.put_u8(6);
211            bytes.put_u8(7);
212            bytes.put_u8(8);
213        }
214
215        bytes.put_u32_le(0x0001);
216
217        let mut cursor = Cursor::new(&mut bytes);
218
219        let packet = decode_telemetry(&mut cursor).unwrap();
220        let telemetry = packet.telemetry()[0];
221
222        assert_eq!(1, telemetry.speed());
223        assert_approx_eq!(2.0, telemetry.throttle());
224        assert_approx_eq!(3.0, telemetry.steering());
225        assert_approx_eq!(4.0, telemetry.brake());
226        assert_eq!(5, telemetry.clutch());
227        assert_eq!(Gear::Sixth, telemetry.gear());
228        assert_eq!(7, telemetry.engine_rpm());
229        assert!(telemetry.drs());
230        assert_eq!(9, telemetry.rev_lights());
231        assert_eq!(10, telemetry.brake_temperature().front_left());
232        assert_eq!(14, telemetry.tyre_surface_temperature().front_left());
233        assert_eq!(18, telemetry.tyre_inner_temperature().front_left());
234        assert_eq!(22, telemetry.engine_temperature());
235        assert_approx_eq!(23.0, telemetry.tyre_pressure().front_left());
236        assert_eq!(Surface::Mud, telemetry.surface_type().front_left());
237        assert_eq!(Button::CROSS_OR_A, packet.button_status());
238    }
239}