1use crate::{PointId, TaskId};
2
3#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
4pub struct StatusMessage {
5 #[serde(rename = "ret_code")]
6 pub code: StatusCode,
7 #[serde(rename = "err_msg", default)]
8 pub message: String,
9 #[serde(rename = "create_on", default)]
10 pub timestamp: Option<String>,
11}
12
13impl StatusMessage {
14 pub fn into_result(self) -> Result<(), StatusMessage> {
16 if self.code == StatusCode::Success {
17 Ok(())
18 } else {
19 Err(self)
20 }
21 }
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive)]
25#[repr(u32)]
26pub enum StatusCode {
27 Success = 0,
29 Unavailable = 40000,
30 ParamMissing = 40001,
32 ParamTypeError = 40002,
34 ParamIllegal = 40003,
36 ModeError = 40004,
38 IllegalMapName = 40005,
40 ProgrammingDsp = 40006,
42 ProgramDspError = 40007,
44 ShutdownError = 40010,
46 RebootError = 40011,
48 MapParseError = 40050,
50 MapNotExists = 40051,
52 LoadMapError = 40052,
54 LoadMapobjError = 40053,
56 EmptyMap = 40054,
58 ReqTimeout = 40100,
60 ReqForbidden = 40101,
62 RobotBusy = 40102,
64 RobotInternalError = 40199,
66 InitStatusError = 41000,
68 LoadmapStatusError = 41001,
70 RelocStatusError = 41002,
72
73 #[num_enum(default)]
75 Custom,
76}
77
78macro_rules! impl_serde_for_num_enum {
80 ($enum_type:ty) => {
81 impl<'de> serde::Deserialize<'de> for $enum_type {
82 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
83 where
84 D: serde::Deserializer<'de>,
85 {
86 let code = u32::deserialize(deserializer)?;
87 Ok(<$enum_type>::from(code))
88 }
89 }
90
91 impl serde::Serialize for $enum_type {
92 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
93 where
94 S: serde::Serializer,
95 {
96 serializer.serialize_u32(*self as u32)
97 }
98 }
99 };
100}
101
102impl_serde_for_num_enum!(StatusCode);
103impl_serde_for_num_enum!(JackOperationStatus);
104
105pub trait FromResponseBody: Sized {
106 type Response: serde::de::DeserializeOwned;
107}
108
109#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
110pub struct CommonInfo {
111 pub id: String,
112 pub version: String,
113 pub model: String,
114 #[serde(rename = "ret_code", default)]
115 pub code: Option<StatusCode>,
116 #[serde(rename = "err_msg", default)]
117 pub message: String,
118}
119
120#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
121pub struct OperationInfo {
122 #[serde(rename = "odo")]
123 pub mileage: f64,
124 #[serde(rename = "total")]
125 pub session_time_ms: f64,
126 #[serde(rename = "total_time")]
127 pub total_time_ms: f64,
128 pub controller_temp: f64,
130 #[serde(default)]
132 pub controller_humi: f64,
133 #[serde(default)]
135 pub controller_voltage: f64,
136
137 #[serde(rename = "ret_code", default)]
138 pub code: Option<StatusCode>,
139 #[serde(rename = "err_msg", default)]
140 pub message: String,
141}
142
143#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
144pub struct RobotPose {
145 pub x: f64,
147 pub y: f64,
149 pub angle: f64,
151
152 pub confidence: f64,
154
155 #[serde(rename = "ret_code", default)]
156 pub code: Option<StatusCode>,
157 #[serde(rename = "err_msg", default)]
158 pub message: String,
159}
160
161#[derive(Debug, Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive)]
162#[repr(u8)]
163pub enum BlockReason {
164 Laser = 1,
165 Fallingdown = 2,
166 Collision = 3,
167 Infrared = 4,
168
169 #[num_enum(default)]
170 Custom,
171}
172
173impl std::fmt::Display for BlockReason {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 let description = match self {
176 BlockReason::Laser => "Laser Obstacle",
177 BlockReason::Fallingdown => "Falling Down",
178 BlockReason::Collision => "Collision Detected",
179 BlockReason::Infrared => "Infrared Obstacle",
180 BlockReason::Custom => "Custom Reason",
181 };
182
183 write!(f, "{}", description)
184 }
185}
186
187impl<'de> serde::Deserialize<'de> for BlockReason {
188 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
189 where
190 D: serde::Deserializer<'de>,
191 {
192 let code = u8::deserialize(deserializer)?;
193 Ok(BlockReason::from(code))
194 }
195}
196
197impl serde::Serialize for BlockReason {
198 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
199 where
200 S: serde::Serializer,
201 {
202 serializer.serialize_u8(*self as u8)
203 }
204}
205
206#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
207pub struct BlockStatus {
208 #[serde(rename = "blocked")]
209 pub is_blocked: bool,
210 #[serde(rename = "block_reason", default)]
211 pub reason: Option<BlockReason>,
212 #[serde(rename = "block_x", default)]
213 pub x: Option<f64>,
214 #[serde(rename = "block_y", default)]
215 pub y: Option<f64>,
216
217 #[serde(rename = "ret_code")]
218 pub code: StatusCode,
219 #[serde(rename = "err_msg", default)]
220 pub message: String,
221}
222
223#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
224pub struct BatteryStatus {
225 pub battery_level: f64,
227 pub battery_temp: f64,
229 pub charging: bool,
231 pub voltage: f64,
233 pub current: f64,
235
236 #[serde(rename = "ret_code", default)]
237 pub code: Option<StatusCode>,
238 #[serde(rename = "err_msg", default)]
239 pub message: String,
240}
241
242#[derive(Debug, Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive)]
243#[repr(u32)]
244pub enum JackOperationStatus {
245 Rising = 0x0,
246 RisingInPlace = 0x1,
247 Lowering = 0x2,
248 LoweringInPlace = 0x3,
249 Stop = 0x4,
250 #[num_enum(default)]
251 Failed = 0xFF,
252}
253
254#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
273pub struct JackStatus {
274 #[serde(rename = "jack_mode")]
276 pub automatic_mode: bool,
277
278 #[serde(rename = "jack_enable")]
279 pub enabled: bool,
280
281 #[serde(rename = "jack_error_code")]
282 pub error_code: u32,
283
284 #[serde(rename = "jack_state")]
286 pub operation: JackOperationStatus,
287
288 #[serde(rename = "jack_isFull")]
289 pub has_payload: bool,
290 #[serde(rename = "jack_speed")]
292 pub speed: u32,
293 #[serde(rename = "jack_emc")]
295 pub emergency_stop: bool,
296 #[serde(rename = "jack_height")]
298 pub height: f64,
299 #[serde(rename = "peripheral_data")]
301 pub peripheral_data: Vec<u8>,
302
303 #[serde(rename = "ret_code", default)]
304 pub code: Option<StatusCode>,
305 #[serde(rename = "err_msg", default)]
306 pub message: String,
307
308 #[serde(rename = "create_on", default)]
310 pub timestamp: Option<String>,
311}
312
313#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
314pub struct NavStatus {
315 #[serde(rename = "task_status")]
316 pub status: TaskStatus,
317 #[serde(rename = "task_type")]
318 pub ty: TaskType,
319 pub target_id: PointId,
320 pub target_point: [f64; 3],
322
323 pub finished_path: Vec<PointId>,
327
328 pub unfinished_path: Vec<PointId>,
332
333 pub move_status_info: String,
335
336 #[serde(rename = "ret_code", default)]
338 pub code: Option<StatusCode>,
339 pub create_on: Option<String>,
341 #[serde(rename = "err_msg", default)]
343 pub message: String,
344}
345
346#[derive(Debug, Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive)]
347#[repr(u32)]
348pub enum TaskType {
349 NoNav = 0,
350 FreeNavToPoint = 1,
351 FreeNavToSite = 2,
352 PathNavToSite = 3,
353 Manual = 7,
354 #[num_enum(default)]
355 Other = 100,
356}
357
358impl_serde_for_num_enum!(TaskType);
359
360#[derive(Debug, Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive)]
361#[repr(u32)]
362pub enum TaskStatus {
363 #[num_enum(default)]
364 None = 0,
365 Waiting = 1,
366 Running = 2,
367 Suspended = 3,
368 Completed = 4,
369 Failed = 5,
370 Canceled = 6,
371 OverTime = 7,
372 NotFound = 404,
373}
374
375impl_serde_for_num_enum!(TaskStatus);
376
377#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
378pub struct TaskStatusItem {
379 pub task_id: TaskId,
380 pub status: TaskStatus,
381}
382
383#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
384pub struct TaskPackage {
385 pub closest_target: PointId,
387 pub source_name: TaskId,
389 pub target_name: TaskId,
391 pub percentage: f64,
394 pub distance: Option<f64>,
397
398 #[serde(rename = "task_status_list")]
399 pub tasks: Vec<TaskStatusItem>,
400 pub info: String,
403
404 #[serde(rename = "ret_code", default)]
405 pub code: Option<StatusCode>,
406 #[serde(rename = "err_msg", default)]
407 pub message: String,
408 pub create_on: Option<String>,
409}
410
411#[cfg(test)]
412mod tests {
413 use crate::StatusCode;
414
415 #[test]
416 fn test_error_code_serialization() {
417 use serde::{Deserialize, Serialize};
418
419 #[derive(Serialize, Deserialize)]
420 struct TestStruct {
421 code: StatusCode,
422 }
423
424 let test_instance = TestStruct {
425 code: StatusCode::ParamMissing,
426 };
427
428 let serialized = serde_json::to_string(&test_instance).unwrap();
429 assert_eq!(serialized, r#"{"code":40001}"#);
430
431 let deserialized: TestStruct =
432 serde_json::from_str(&serialized).unwrap();
433 assert_eq!(deserialized.code, StatusCode::ParamMissing);
434
435 let custom_code = r#"{"code":99999}"#;
436 let deserialized_custom: TestStruct =
437 serde_json::from_str(custom_code).unwrap();
438 assert_eq!(deserialized_custom.code, StatusCode::Custom);
439 }
440
441 #[test]
442 #[allow(clippy::approx_constant)]
443 fn test_robot_pose_serialization_deserializatio() {
444 let with_error_code = r#"
445 {
446 "x": 1.0,
447 "y": 2.0,
448 "angle": 0.7854,
449 "confidence": 0.95,
450 "ret_code": 40000,
451 "err_msg": "msg"
452 }"#;
453
454 let pose: super::RobotPose =
455 serde_json::from_str(with_error_code).unwrap();
456 assert_eq!(pose.x, 1.0);
457 assert_eq!(pose.y, 2.0);
458 assert!((pose.angle - 0.7854).abs() < 0.0001);
459 assert_eq!(pose.confidence, 0.95);
460 assert_eq!(pose.code, Some(StatusCode::Unavailable));
461 assert_eq!(pose.message, "msg");
462
463 let without_error_code = r#"
464 {
465 "x": 3.0,
466 "y": 4.0,
467 "angle": 1.5708,
468 "confidence": 0.9
469 }"#;
470 let pose_no_code: super::RobotPose =
471 serde_json::from_str(without_error_code).unwrap();
472 assert_eq!(pose_no_code.x, 3.0);
473 assert_eq!(pose_no_code.y, 4.0);
474 assert!((pose_no_code.angle - 1.5708).abs() < 0.0001);
475 assert_eq!(pose_no_code.confidence, 0.9);
476 assert_eq!(pose_no_code.code, None);
477 assert_eq!(pose_no_code.message, "");
478 }
479
480 #[test]
481 fn test_block_status_serialization_deserialization() {
482 let with_error_code = r#"
483 {
484 "blocked": true,
485 "block_reason": 2,
486 "block_x": 1.5,
487 "block_y": 2.5,
488 "ret_code": 40002,
489 "err_msg": "Parameter type error"
490 }"#;
491
492 let status: super::BlockStatus =
493 serde_json::from_str(with_error_code).unwrap();
494 assert!(status.is_blocked);
495 assert_eq!(status.reason, Some(super::BlockReason::Fallingdown));
496 assert_eq!(status.x, Some(1.5));
497 assert_eq!(status.y, Some(2.5));
498 assert_eq!(status.code, StatusCode::ParamTypeError);
499 assert_eq!(status.message, "Parameter type error");
500
501 let without_error_code = r#"
502 {
503 "ret_code": 0,
504 "blocked": false
505 }"#;
506 let status_no_code: super::BlockStatus =
507 serde_json::from_str(without_error_code).unwrap();
508 assert!(!status_no_code.is_blocked);
509 assert_eq!(status_no_code.reason, None);
510 assert_eq!(status_no_code.x, None);
511 assert_eq!(status_no_code.y, None);
512 assert_eq!(status_no_code.code, StatusCode::Success);
513 assert_eq!(status_no_code.message, "");
514 }
515}