1use binrw::binread;
2use chrono::{DateTime, Utc};
3use serde::Serialize;
4use std::io::SeekFrom;
5#[cfg(target_arch = "wasm32")]
6use tsify_next::Tsify;
7
8#[binread]
9#[derive(Debug, Serialize, Clone)]
10#[serde(rename_all = "camelCase")]
11#[br(little, import(version: u8))]
12#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
13pub struct Details {
14 #[br(count=20, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string())]
15 pub sub_street: String,
16 #[br(count=20, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string())]
17 pub street: String,
18 #[br(count=20, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string())]
19 pub city: String,
20 #[br(count=20, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string())]
21 pub area: String,
22 pub is_favorite: u8,
23 pub is_new: u8,
24 pub needs_upload: u8,
25 pub record_line_count: i32,
26 pub detail_info_checksum: i32,
27 #[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
28 #[br(map = |x: i64| DateTime::from_timestamp(x / 1000, (x % 1000 * 1000000) as u32).unwrap_or_default())]
29 pub start_time: DateTime<Utc>,
30 pub longitude: f64,
32 pub latitude: f64,
34 pub total_distance: f32,
36 #[br(map = |x: i32| x as f64 / 1000.0)]
38 pub total_time: f64,
39 pub max_height: f32,
41 pub max_horizontal_speed: f32,
43 pub max_vertical_speed: f32,
45 pub capture_num: i32,
46 pub video_time: i64,
47 pub moment_pic_image_buffer_len: [i32; 4],
48 pub moment_pic_shrink_image_buffer_len: [i32; 4],
49 #[br(map = |v: [f64; 4]| v.map(|rad: f64| rad.to_degrees()) )]
51 pub moment_pic_longitude: [f64; 4],
52 #[br(map = |v: [f64; 4]| v.map(|rad: f64| rad.to_degrees()) )]
54 pub moment_pic_latitude: [f64; 4],
55 #[br(temp)]
56 _analysis_offset: i64,
57 #[br(temp)]
58 _user_api_center_id_md5: [u8; 16],
59 #[br(seek_before = if version <= 5 { SeekFrom::Start(352) } else { SeekFrom::Current(0) })]
60 pub take_off_altitude: f32,
61 #[br(
62 seek_before = if version <= 5 { SeekFrom::Start(277) } else { SeekFrom::Current(0) },
63 map = |x: u8| ProductType::from(x))
64 ]
65 pub product_type: ProductType,
66 #[br(temp)]
67 _activation_timestamp: i64,
68 #[br(
69 seek_before = if version <= 5 { SeekFrom::Start(278) } else { SeekFrom::Current(0) },
70 count = if version <= 5 { 24 } else { 32 }, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string()
71 )]
72 pub aircraft_name: String,
73 #[br(
74 seek_before = if version <= 5 { SeekFrom::Start(267) } else { SeekFrom::Current(0) },
75 count = if version <= 5 { 10 } else { 16 }, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string()
76 )]
77 pub aircraft_sn: String,
78 #[br(
79 seek_before = if version <= 5 { SeekFrom::Start(318) } else { SeekFrom::Current(0) },
80 count = if version <= 5 { 10 } else { 16 }, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string()
81 )]
82 pub camera_sn: String,
83 #[br(count = if version <= 5 { 10 } else { 16 }, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string())]
84 pub rc_sn: String,
85 #[br(count = if version <= 5 { 10 } else { 16 }, map = |s: Vec<u8>| String::from_utf8_lossy(&s).trim_end_matches('\0').to_string())]
86 pub battery_sn: String,
87 #[br(map = |x: u8| Platform::from(x))]
88 pub app_platform: Platform,
89 #[br(map = |x: [u8; 3]| format!("{}.{}.{}", x[0], x[1], x[2]))]
90 pub app_version: String,
91}
92
93#[derive(Serialize, Debug, Clone, PartialEq, Default, Copy)]
94#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
95pub enum ProductType {
96 #[default]
97 None,
98 Inspire1,
99 Phantom3Standard,
100 Phantom3Advanced,
101 Phantom3Pro,
102 OSMO,
103 Matrice100,
104 Phantom4,
105 LB2,
106 Inspire1Pro,
107 A3,
108 Matrice600,
109 Phantom34K,
110 MavicPro,
111 ZenmuseXT,
112 Inspire1RAW,
113 A2,
114 Inspire2,
115 OSMOPro,
116 OSMORaw,
117 OSMOPlus,
118 Mavic,
119 OSMOMobile,
120 OrangeCV600,
121 Phantom4Pro,
122 N3FC,
123 Spark,
124 Matrice600Pro,
125 Phantom4Advanced,
126 Phantom3SE,
127 AG405,
128 Matrice200,
129 Matrice210,
130 Matrice210RTK,
131 MavicAir,
132 Mavic2,
133 Phantom4ProV2,
134 Phantom4RTK,
135 Phantom4Multispectral,
136 Mavic2Enterprise,
137 MavicMini,
138 Matrice200V2,
139 Matrice210V2,
140 Matrice210RTKV2,
141 MavicAir2,
142 Matrice300RTK,
143 FPV,
144 MavicAir2S,
145 Mini2,
146 Mavic3,
147 MiniSE,
148 Mini3Pro,
149 Mavic3Pro,
150 Mini2SE,
151 Matrice30,
152 Mavic3Enterprise,
153 Avata,
154 Mini4Pro,
155 Avata2,
156 Matrice350RTK,
157 #[serde(untagged)]
158 Unknown(u8),
159}
160
161impl From<u8> for ProductType {
162 fn from(num: u8) -> Self {
163 match num {
164 0 => ProductType::None,
165 1 => ProductType::Inspire1,
166 2 => ProductType::Phantom3Standard,
167 3 => ProductType::Phantom3Advanced,
168 4 => ProductType::Phantom3Pro,
169 5 => ProductType::OSMO,
170 6 => ProductType::Matrice100,
171 7 => ProductType::Phantom4,
172 8 => ProductType::LB2,
173 9 => ProductType::Inspire1Pro,
174 10 => ProductType::A3,
175 11 => ProductType::Matrice600,
176 12 => ProductType::Phantom34K,
177 13 => ProductType::MavicPro,
178 14 => ProductType::ZenmuseXT,
179 15 => ProductType::Inspire1RAW,
180 16 => ProductType::A2,
181 17 => ProductType::Inspire2,
182 18 => ProductType::OSMOPro,
183 19 => ProductType::OSMORaw,
184 20 => ProductType::OSMOPlus,
185 21 => ProductType::Mavic,
186 22 => ProductType::OSMOMobile,
187 23 => ProductType::OrangeCV600,
188 24 => ProductType::Phantom4Pro,
189 25 => ProductType::N3FC,
190 26 => ProductType::Spark,
191 27 => ProductType::Matrice600Pro,
192 28 => ProductType::Phantom4Advanced,
193 29 => ProductType::Phantom3SE,
194 30 => ProductType::AG405,
195 31 => ProductType::Matrice200,
196 33 => ProductType::Matrice210,
197 34 => ProductType::Matrice210RTK,
198 38 => ProductType::MavicAir,
199 42 => ProductType::Mavic2,
200 44 => ProductType::Phantom4ProV2,
201 46 => ProductType::Phantom4RTK,
202 57 => ProductType::Phantom4Multispectral,
203 58 => ProductType::Mavic2Enterprise,
204 59 => ProductType::MavicMini,
205 60 => ProductType::Matrice200V2,
206 61 => ProductType::Matrice210V2,
207 62 => ProductType::Matrice210RTKV2,
208 67 => ProductType::MavicAir2,
209 70 => ProductType::Matrice300RTK,
210 73 => ProductType::FPV,
211 75 => ProductType::MavicAir2S,
212 76 => ProductType::Mini2,
213 77 => ProductType::Mavic3,
214 96 => ProductType::MiniSE,
215 103 => ProductType::Mini3Pro,
216 111 => ProductType::Mavic3Pro,
217 113 => ProductType::Mini2SE,
218 116 => ProductType::Matrice30,
219 118 => ProductType::Mavic3Enterprise,
220 121 => ProductType::Avata,
221 126 => ProductType::Mini4Pro,
222 152 => ProductType::Avata2,
223 170 => ProductType::Matrice350RTK,
224 _ => ProductType::Unknown(num),
225 }
226 }
227}
228
229impl ProductType {
230 pub fn battery_cell_num(&self) -> u8 {
231 match self {
232 ProductType::Inspire1 => 6,
233 ProductType::Phantom3Standard => 4,
234 ProductType::Phantom3Advanced => 4,
235 ProductType::Phantom3Pro => 4,
236 ProductType::Matrice100 => 6,
237 ProductType::Phantom4 => 4,
238 ProductType::Inspire1Pro => 6,
239 ProductType::Matrice600 => 6,
240 ProductType::Phantom34K => 4,
241 ProductType::MavicPro => 3,
242 ProductType::Inspire1RAW => 6,
243 ProductType::Inspire2 => 6,
244 ProductType::Mavic => 3,
245 ProductType::Phantom4Pro => 4,
246 ProductType::Spark => 3,
247 ProductType::Matrice600Pro => 6,
248 ProductType::Phantom4Advanced => 4,
249 ProductType::Phantom3SE => 4,
250 ProductType::Matrice200 => 6,
251 ProductType::Matrice210 => 6,
252 ProductType::Matrice210RTK => 6,
253 ProductType::MavicAir => 3,
254 ProductType::Mavic2 => 4,
255 ProductType::Phantom4ProV2 => 4,
256 ProductType::Phantom4RTK => 4,
257 ProductType::Phantom4Multispectral => 4,
258 ProductType::Mavic2Enterprise => 4,
259 ProductType::MavicMini => 2,
260 ProductType::Matrice200V2 => 6,
261 ProductType::Matrice210V2 => 6,
262 ProductType::Matrice210RTKV2 => 6,
263 ProductType::MavicAir2 => 3,
264 ProductType::Matrice300RTK => 12,
265 ProductType::FPV => 6,
266 ProductType::MavicAir2S => 3,
267 ProductType::Mini2 => 2,
268 ProductType::Mavic3 => 4,
269 ProductType::MiniSE => 2,
270 ProductType::Mini3Pro => 2,
271 ProductType::Mavic3Pro => 4,
272 ProductType::Mini2SE => 2,
273 ProductType::Matrice30 => 6,
274 ProductType::Mavic3Enterprise => 4,
275 ProductType::Avata => 5,
276 ProductType::Mini4Pro => 2,
277 ProductType::Avata2 => 4,
278 ProductType::Matrice350RTK => 12,
279 _ => 4,
280 }
281 }
282
283 pub fn battery_num(&self) -> u8 {
284 match self {
285 ProductType::Inspire1 => 2,
286 ProductType::Phantom3Standard => 1,
287 ProductType::Phantom3Advanced => 1,
288 ProductType::Phantom3Pro => 1,
289 ProductType::Matrice100 => 2,
290 ProductType::Phantom4 => 1,
291 ProductType::Inspire1Pro => 2,
292 ProductType::Matrice600 => 6,
293 ProductType::Phantom34K => 1,
294 ProductType::MavicPro => 1,
295 ProductType::Inspire1RAW => 2,
296 ProductType::Inspire2 => 2,
297 ProductType::Mavic => 1,
298 ProductType::Phantom4Pro => 1,
299 ProductType::Spark => 1,
300 ProductType::Matrice600Pro => 6,
301 ProductType::Phantom4Advanced => 1,
302 ProductType::Phantom3SE => 1,
303 ProductType::Matrice200 => 2,
304 ProductType::Matrice210 => 2,
305 ProductType::Matrice210RTK => 2,
306 ProductType::MavicAir => 1,
307 ProductType::Mavic2 => 1,
308 ProductType::Phantom4ProV2 => 1,
309 ProductType::Phantom4RTK => 1,
310 ProductType::Phantom4Multispectral => 1,
311 ProductType::Mavic2Enterprise => 1,
312 ProductType::MavicMini => 1,
313 ProductType::Matrice200V2 => 2,
314 ProductType::Matrice210V2 => 2,
315 ProductType::Matrice210RTKV2 => 2,
316 ProductType::MavicAir2 => 1,
317 ProductType::Matrice300RTK => 2,
318 ProductType::FPV => 1,
319 ProductType::MavicAir2S => 1,
320 ProductType::Mini2 => 1,
321 ProductType::Mavic3 => 1,
322 ProductType::MiniSE => 1,
323 ProductType::Mini3Pro => 1,
324 ProductType::Mavic3Pro => 1,
325 ProductType::Mini2SE => 1,
326 ProductType::Matrice30 => 2,
327 ProductType::Mavic3Enterprise => 1,
328 ProductType::Avata => 1,
329 ProductType::Mini4Pro => 1,
330 ProductType::Avata2 => 1,
331 ProductType::Matrice350RTK => 2,
332 _ => 1,
333 }
334 }
335}
336
337#[derive(Serialize, Debug, Clone, PartialEq)]
338#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
339pub enum Platform {
340 IOS,
341 Android,
342 DJIFly,
343 Windows,
344 Mac,
345 Linux,
346 #[serde(untagged)]
347 Unknown(u8),
348}
349
350impl From<u8> for Platform {
351 fn from(num: u8) -> Self {
352 match num {
353 1 => Platform::IOS,
354 2 => Platform::Android,
355 6 => Platform::DJIFly,
356 10 => Platform::Windows,
357 11 => Platform::Mac,
358 12 => Platform::Linux,
359 _ => Platform::Unknown(num),
360 }
361 }
362}