1use crate::{ApiRequest, PointId, TaskId};
2
3pub trait ToRequestBody {
4 fn to_request_body(&self) -> Result<String, serde_json::Error>;
6 fn to_api_request(&self) -> ApiRequest;
7}
8
9pub const SELF_POSITION: &str = "SELF_POSITION";
10
11#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
12pub struct MoveToPoint {
13 pub id: PointId,
14 pub x: Option<f64>,
15 pub y: Option<f64>,
16
17 pub angle: Option<f64>,
18 pub max_speed: Option<f64>,
19 pub max_wspeed: Option<f64>,
20 pub max_acc: Option<f64>,
21 pub max_wacc: Option<f64>,
22}
23
24impl MoveToPoint {
25 pub fn zeros() -> Self {
27 Self::default()
28 }
29
30 pub fn with_id<T: Into<String>>(id: T) -> Self {
31 Self {
32 id: id.into(),
33 ..Default::default()
34 }
35 }
36
37 pub fn new(x: f64, y: f64) -> Self {
38 Self {
39 x: Some(x),
40 y: Some(y),
41 ..Default::default()
42 }
43 }
44}
45
46#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
47#[serde(rename_all = "lowercase")]
48pub enum MoveMethod {
49 Forward,
50 Backward,
51}
52
53#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
54pub struct GetNavStatus {
55 pub simple: Option<bool>,
57}
58
59impl GetNavStatus {
60 pub fn new() -> Self {
61 Self { simple: None }
62 }
63
64 pub fn with_simple(mut self, simple: bool) -> Self {
65 self.simple = Some(simple);
66 self
67 }
68}
69
70impl Default for GetNavStatus {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76#[derive(
77 Debug, Clone, serde::Serialize, serde::Deserialize, Default, PartialEq,
78)]
79pub struct MoveToTarget {
80 #[serde(rename = "id")]
83 pub target: PointId,
84 #[serde(rename = "source_id")]
88 pub start: PointId,
89
90 pub task_id: Option<TaskId>,
94
95 pub method: Option<MoveMethod>,
97
98 pub spin: Option<bool>,
100
101 #[serde(default)]
103 pub delay: u64,
104
105 pub start_rot_dir: Option<i8>,
110
111 pub end_rot_dir: Option<i8>,
116
117 pub reach_dist: Option<f64>,
119
120 pub reach_angle: Option<f64>,
122
123 pub angle: Option<f64>,
124 pub max_speed: Option<f64>,
125 pub max_wspeed: Option<f64>,
126 pub max_acc: Option<f64>,
127 pub max_wacc: Option<f64>,
128
129 #[serde(flatten)]
130 pub jack_operation: Option<JackOperation>,
131}
132
133macro_rules! impl_move_to_target_builder {
136 ( $($method_name:ident : $field_name:ident = $field_type:ty),* $(,)? ) => {
137 $(
138 pub fn $method_name(mut self, value: $field_type) -> Self {
139 self.$field_name = value.into();
140 self
141 }
142 )*
143 };
144}
145
146impl MoveToTarget {
147 pub fn new<T: Into<String>>(target: T) -> Self {
148 Self {
149 target: target.into(),
150 start: SELF_POSITION.to_string(),
151 ..Default::default()
152 }
153 }
154
155 impl_move_to_target_builder! {
156 with_task_id: task_id = TaskId,
157 with_start: start = PointId,
158 with_method: method = MoveMethod,
159 with_operation: jack_operation = JackOperation,
160 }
161}
162
163#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
164#[serde(tag = "operation")]
165pub enum JackOperation {
166 JackLoad,
167 JackUnload,
168 JackHeight { jack_height: f64 },
169 Wait,
170}
171
172#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
173pub struct SetJackHeight {
174 pub height: f64,
175}
176
177impl SetJackHeight {
178 pub fn new(height: f64) -> Self {
179 Self { height }
180 }
181}
182
183#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
184pub struct MoveDesignedPath {
185 #[serde(rename = "move_task_list")]
186 pub path: Vec<MoveToTarget>,
187}
188
189impl MoveDesignedPath {
190 pub fn new(path: impl IntoIterator<Item = MoveToTarget>) -> Self {
191 Self {
192 path: path.into_iter().collect(),
193 }
194 }
195}
196
197#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
198pub struct GetTaskStatus {
199 pub task_ids: Vec<String>,
203}
204
205impl FromIterator<String> for GetTaskStatus {
206 fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
207 Self {
208 task_ids: iter.into_iter().collect(),
209 }
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216 #[test]
217 fn test_move_to_point_serialization() {
218 let raw_json = r#"
219 {
220 "id": "AP1",
221 "source_id": "LM2",
222 "task_id": "12344321",
223 "operation": "JackHeight",
224 "jack_height": 0.2
225 }
226 "#;
227
228 let m1: MoveToTarget = serde_json::from_str(raw_json).unwrap();
229
230 let m2 = MoveToTarget {
231 target: "AP1".to_string(),
232 start: "LM2".to_string(),
233 task_id: Some("12344321".to_string()),
234 jack_operation: Some(JackOperation::JackHeight {
235 jack_height: 0.2,
236 }),
237 ..Default::default()
238 };
239
240 let serialized = serde_json::to_string_pretty(&m2).unwrap();
241 let m2 = serde_json::from_str::<MoveToTarget>(&serialized).unwrap();
242
243 eprintln!("Serialized: {}", serialized);
244 assert_eq!(m1, m2);
245
246 let raw_json = r#"
247 {
248 "id": "AP1",
249 "source_id": "LM2",
250 "task_id": "12344321",
251 "operation": "JackLoad"
252 }
253 "#;
254 let m1: MoveToTarget = serde_json::from_str(raw_json).unwrap();
255 let m2 = MoveToTarget {
256 target: "AP1".to_string(),
257 start: "LM2".to_string(),
258 task_id: Some("12344321".to_string()),
259 jack_operation: Some(JackOperation::JackLoad),
260 ..Default::default()
261 };
262 let serialized = serde_json::to_string_pretty(&m2).unwrap();
263 let m2 = serde_json::from_str::<MoveToTarget>(&serialized).unwrap();
264 assert_eq!(m1, m2);
265 }
266}