blackbox_log/
event.rs
1use tracing::instrument;
4
5use crate::parser::{decode, InternalError, InternalResult};
6use crate::Reader;
7
8#[derive(Debug, Clone, PartialEq)]
10#[cfg_attr(feature = "_serde", derive(serde::Serialize))]
11pub enum Event {
12 SyncBeep(u64),
13 InflightAdjustment {
14 function: u8,
15 new_value: AdjustedValue,
16 },
17 Resume {
18 log_iteration: u32,
19 time: u32,
20 },
21 Disarm(u32),
22 FlightMode {
23 flags: u32,
24 last_flags: u32,
25 },
26 ImuFailure {
27 error: u32,
28 },
29 End {
30 disarm_reason: Option<u32>,
31 },
32}
33
34#[derive(Debug, Clone, Copy, PartialEq)]
37#[cfg_attr(feature = "_serde", derive(serde::Serialize))]
38pub enum AdjustedValue {
39 Float(f32),
40 Int(i32),
41}
42
43impl Event {
44 #[instrument(level = "debug", name = "Event::parse", skip_all, fields(kind))]
45 pub(crate) fn parse(data: &mut Reader) -> InternalResult<Self> {
46 let byte = data.read_u8().ok_or(InternalError::Eof)?;
47 let kind = EventKind::from_byte(byte).ok_or_else(|| {
48 tracing::debug!("found invalid event: {byte:0>#2x}");
49 InternalError::Retry
50 })?;
51
52 let event = match kind {
53 EventKind::SyncBeep => {
54 let time = decode::variable(data)?;
57 Self::SyncBeep(time.into())
58 }
59
60 EventKind::InflightAdjustment => {
61 let function = data.read_u8().ok_or(InternalError::Eof)?;
62
63 let new_value = if (function & 0x80) > 0 {
64 AdjustedValue::Float(data.read_f32().ok_or(InternalError::Eof)?)
65 } else {
66 AdjustedValue::Int(decode::variable_signed(data)?)
67 };
68
69 Self::InflightAdjustment {
70 function: function & 0x7F,
71 new_value,
72 }
73 }
74
75 EventKind::Resume => {
76 let log_iteration = decode::variable(data)?;
77 let time = decode::variable(data)?;
78
79 Self::Resume {
80 log_iteration,
81 time,
82 }
83 }
84
85 EventKind::Disarm => {
86 let reason = decode::variable(data)?;
87 Self::Disarm(reason)
88 }
89
90 EventKind::FlightMode => {
91 let flags = decode::variable(data)?;
92 let last_flags = decode::variable(data)?;
93 Self::FlightMode { flags, last_flags }
94 }
95
96 EventKind::ImuFailure => {
97 let error = decode::variable(data)?;
98 Self::ImuFailure { error }
99 }
100
101 EventKind::End => {
102 check_message(data, b"End of log")?;
103
104 let disarm_reason = if data.peek() == Some(b' ') {
105 check_message(data, b" (disarm reason:")?;
109
110 let reason = data.read_u8().ok_or(InternalError::Eof)?.into();
111
112 if data.read_u8() != Some(b')') {
113 return Err(InternalError::Retry);
114 }
115
116 Some(reason)
117 } else {
118 None
119 };
120
121 if data.read_u8() != Some(0) {
122 return Err(InternalError::Retry);
123 }
124
125 Self::End { disarm_reason }
126 }
127 };
128
129 Ok(event)
130 }
131}
132
133byte_enum! {
134 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
135 #[repr(u8)]
136 pub(crate) enum EventKind {
137 SyncBeep = 0,
138 InflightAdjustment = 13,
139 Resume = 14,
140 Disarm = 15,
141 FlightMode = 30,
142 ImuFailure = 40,
143 End = 255,
144 }
145}
146
147fn check_message(bytes: &mut Reader, message: &[u8]) -> InternalResult<()> {
148 let bytes = bytes.read_n_bytes(message.len());
149
150 if bytes.len() != message.len() {
151 return Err(InternalError::Eof);
152 }
153
154 if bytes != message {
155 return Err(InternalError::Retry);
156 }
157
158 Ok(())
159}