1use crate::definitions::V2NumberValue;
2use crate::helper_functions::{get_f64_value, get_f64_value_for_path, F64CompatiblePath};
3use crate::{SignalKGetError, V1CommonValueFields};
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
7#[serde(rename_all = "camelCase")]
8pub struct V1Steering {
9 pub rudder_angle: Option<V2NumberValue>,
10 pub rudder_angle_target: Option<V2NumberValue>,
11 pub autopilot: Option<V1SteeringAutopilot>,
12}
13
14impl F64CompatiblePath for V1Steering {
15 fn get_f64_for_path(&self, path: &mut Vec<&str>) -> Result<f64, SignalKGetError> {
16 match path[0] {
17 "rudderAngle" => get_f64_value(&self.rudder_angle),
18 "rudderAngleTarget" => get_f64_value(&self.rudder_angle_target),
19 "autopilot" => get_f64_value_for_path(path, &self.autopilot),
20 &_ => Err(SignalKGetError::NoSuchPath),
21 }
22 }
23}
24
25#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
26#[serde(rename_all = "camelCase")]
27pub struct V1SteeringAutopilot {
28 pub state: Option<V1SteeringAutopilotState>,
29 pub mode: Option<V1SteeringAutopilotMode>,
30 pub target: Option<V1SteeringAutopilotTarget>,
31 pub dead_zone: Option<V2NumberValue>,
32 pub backlash: Option<V2NumberValue>,
33 pub gain: Option<V2NumberValue>,
34 pub max_drive_current: Option<V2NumberValue>,
35 pub max_drive_rate: Option<V2NumberValue>,
36 pub port_lock: Option<V2NumberValue>,
37 pub starboard_lock: Option<V2NumberValue>,
38}
39
40impl F64CompatiblePath for V1SteeringAutopilot {
41 fn get_f64_for_path(&self, path: &mut Vec<&str>) -> Result<f64, SignalKGetError> {
42 match path[0] {
43 &_ => Err(SignalKGetError::NoSuchPath),
44 }
45 }
46}
47
48#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
49#[serde(untagged)]
50pub enum V1SteeringAutopilotState {
51 Expanded(V1SteeringAutopilotStateExpandedValue),
52 Value(V1SteeringAutopilotStateValue),
53}
54
55impl Default for V1SteeringAutopilotState {
56 fn default() -> Self {
57 V1SteeringAutopilotState::Value(V1SteeringAutopilotStateValue::default())
58 }
59}
60#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
61pub struct V1SteeringAutopilotStateExpandedValue {
62 pub value: Option<V1SteeringAutopilotStateValue>,
63 #[serde(flatten)]
64 pub common_value_fields: Option<V1CommonValueFields>,
65}
66
67#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
68#[serde(rename_all = "camelCase")]
69pub enum V1SteeringAutopilotStateValue {
70 #[default]
71 Auto,
72 Standby,
73 Alarm,
74 NoDrift,
75 Wind,
76 DepthContour,
77 Route,
78 DirectControl,
79}
80#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
81#[serde(untagged)]
82pub enum V1SteeringAutopilotMode {
83 Expanded(V1SteeringAutopilotModeExpandedValue),
84 Value(V1SteeringAutopilotModeValue),
85}
86
87impl Default for V1SteeringAutopilotMode {
88 fn default() -> Self {
89 V1SteeringAutopilotMode::Value(V1SteeringAutopilotModeValue::default())
90 }
91}
92#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
93pub struct V1SteeringAutopilotModeExpandedValue {
94 pub value: Option<V1SteeringAutopilotModeValue>,
95 #[serde(flatten)]
96 pub common_value_fields: Option<V1CommonValueFields>,
97}
98
99#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
100#[serde(rename_all = "camelCase")]
101pub enum V1SteeringAutopilotModeValue {
102 #[default]
103 PowerSave,
104 Normal,
105 Accurate,
106}
107
108#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
109#[serde(rename_all = "camelCase")]
110pub struct V1SteeringAutopilotTarget {
111 pub wind_angle_apparent: Option<V2NumberValue>,
112 pub wind_angle_true: Option<V2NumberValue>,
113 pub heading_true: Option<V2NumberValue>,
114 pub heading_magnetic: Option<V2NumberValue>,
115}
116
117impl F64CompatiblePath for V1SteeringAutopilotTarget {
118 fn get_f64_for_path(&self, path: &mut Vec<&str>) -> Result<f64, SignalKGetError> {
119 match path[0] {
120 "windAngleApparent" => get_f64_value(&self.wind_angle_apparent),
121 "windAngleTrue" => get_f64_value(&self.wind_angle_true),
122 "headingTrue" => get_f64_value(&self.heading_true),
123 "headingMagnetic" => get_f64_value(&self.heading_magnetic),
124 &_ => Err(SignalKGetError::NoSuchPath),
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use crate::steering::{
132 V1SteeringAutopilotState, V1SteeringAutopilotStateExpandedValue,
133 V1SteeringAutopilotStateValue,
134 };
135
136 #[test]
137 fn steering_autopilot_value() {
138 let j = r#"{
139 "value" : "auto",
140 "$source": "foo.bar",
141 "timestamp": "2014-08-15T19:00:15.402Z"
142 }"#;
143 println!("{:?}", j);
144 let autopilot: V1SteeringAutopilotState = serde_json::from_str(j).unwrap();
145 println!("{:?}", autopilot);
146 }
147 #[test]
148 fn steering_autopilot_expanded_value() {
149 let j = r#"{
150 "value" : "auto",
151 "$source": "foo.bar",
152 "timestamp": "2014-08-15T19:00:15.402Z"
153 }"#;
154 println!("{:?}", j);
155 let autopilot: V1SteeringAutopilotStateExpandedValue = serde_json::from_str(j).unwrap();
156 println!("{:?}", autopilot);
157 }
158 #[test]
159 fn steering_autopilot_state_value() {
160 let j = r#" "auto" "#;
161 println!("{:?}", j);
162 let autopilot: V1SteeringAutopilotStateValue = serde_json::from_str(j).unwrap();
163 println!("{:?}", autopilot);
164 }
165 #[test]
166 fn serialization_of_stearing_value() {
167 let j = V1SteeringAutopilotStateValue::Auto;
168 println!("{:?}", j);
169 let autopilot = serde_json::to_string(&j).unwrap();
170 println!("{:?}", autopilot);
171 }
172}