1use core::fmt;
10
11use crate::{
12 prelude::*, Ack, Cancellation, CommandPayload, Control, ControlAckMode, IdFormat, QueryAck,
13};
14use deku::prelude::*;
15
16#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, DekuRead, DekuWrite)]
18#[deku(
19 endian = "endian",
20 ctx = "endian: deku::ctx::Endian, packet_header: &PacketHeader"
21)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct Command {
24 cam: ControlAckMode,
26 message_id: u32,
28 #[deku(cond = "cam.controllee_enabled() && cam.controllee_id_format() == IdFormat::Id32bit")]
30 controllee_id: Option<u32>,
31 #[deku(
33 cond = "cam.controllee_enabled() && cam.controllee_id_format() == IdFormat::Uuid128bit"
34 )]
35 controllee_uuid: Option<u128>,
36 #[deku(cond = "cam.controller_enabled() && cam.controller_id_format() == IdFormat::Id32bit")]
38 controller_id: Option<u32>,
39 #[deku(
41 cond = "cam.controller_enabled() && cam.controller_id_format() == IdFormat::Uuid128bit"
42 )]
43 controller_uuid: Option<u128>,
44 #[deku(ctx = "&cam, packet_header")]
45 command_payload: CommandPayload,
46}
47
48impl Default for Command {
49 fn default() -> Self {
50 Self {
51 cam: Default::default(),
52 message_id: Default::default(),
53 controllee_id: Default::default(),
54 controllee_uuid: Default::default(),
55 controller_id: Default::default(),
56 controller_uuid: Default::default(),
57 command_payload: CommandPayload::Control(Control::default()),
58 }
59 }
60}
61
62impl Command {
63 pub fn new_control() -> Command {
65 Command::default()
66 }
67
68 pub fn new_cancellation() -> Command {
70 Self {
71 cam: Default::default(),
72 message_id: Default::default(),
73 controllee_id: Default::default(),
74 controllee_uuid: Default::default(),
75 controller_id: Default::default(),
76 controller_uuid: Default::default(),
77 command_payload: CommandPayload::Cancellation(Cancellation::default()),
78 }
79 }
80
81 pub fn new_validation_ack() -> Command {
83 let mut cam = ControlAckMode::default();
84 cam.set_validation();
85 Self {
86 cam,
87 message_id: Default::default(),
88 controllee_id: Default::default(),
89 controllee_uuid: Default::default(),
90 controller_id: Default::default(),
91 controller_uuid: Default::default(),
92 command_payload: CommandPayload::ValidationAck(Ack::default()),
93 }
94 }
95
96 pub fn new_exec_ack() -> Command {
98 let mut cam = ControlAckMode::default();
99 cam.set_execution();
100 Self {
101 cam,
102 message_id: Default::default(),
103 controllee_id: Default::default(),
104 controllee_uuid: Default::default(),
105 controller_id: Default::default(),
106 controller_uuid: Default::default(),
107 command_payload: CommandPayload::ExecAck(Ack::default()),
108 }
109 }
110
111 pub fn new_query_ack() -> Command {
113 let mut cam = ControlAckMode::default();
114 cam.set_state();
115 Self {
116 cam,
117 message_id: Default::default(),
118 controllee_id: Default::default(),
119 controllee_uuid: Default::default(),
120 controller_id: Default::default(),
121 controller_uuid: Default::default(),
122 command_payload: CommandPayload::QueryAck(QueryAck::default()),
123 }
124 }
125
126 pub fn message_id(&self) -> u32 {
128 self.message_id
129 }
130
131 pub fn set_message_id(&mut self, message_id: u32) {
133 self.message_id = message_id;
134 }
135
136 pub fn cam(&self) -> ControlAckMode {
138 self.cam
139 }
140
141 pub fn set_cam(&mut self, mode: ControlAckMode) {
153 self.cam = mode;
154 }
155
156 pub fn controllee_id(&self) -> Option<u32> {
158 self.controllee_id
159 }
160 pub fn set_controllee_id(&mut self, id: Option<u32>) -> Result<(), VitaError> {
167 if id.is_some() && self.controllee_uuid.is_some() {
168 return Err(VitaError::TriedIdWhenUuidSet);
169 }
170 self.controllee_id = id;
171 if id.is_some() {
172 self.cam.enable_controllee();
173 self.cam.set_controllee_id_format(IdFormat::Id32bit);
174 } else if self.controllee_uuid.is_none() {
175 self.cam.disable_controllee();
176 }
177 Ok(())
178 }
179
180 pub fn controller_id(&self) -> Option<u32> {
182 self.controller_id
183 }
184 pub fn set_controller_id(&mut self, id: Option<u32>) -> Result<(), VitaError> {
191 if id.is_some() && self.controller_uuid.is_some() {
192 return Err(VitaError::TriedIdWhenUuidSet);
193 }
194 self.controller_id = id;
195 if id.is_some() {
196 self.cam.enable_controller();
197 self.cam.set_controller_id_format(IdFormat::Id32bit);
198 } else if self.controller_uuid.is_none() {
199 self.cam.disable_controller();
200 }
201 Ok(())
202 }
203
204 pub fn controllee_uuid(&self) -> Option<u128> {
206 self.controllee_uuid
207 }
208 pub fn set_controllee_uuid(&mut self, uuid: Option<u128>) -> Result<(), VitaError> {
215 if uuid.is_some() && self.controllee_id.is_some() {
216 return Err(VitaError::TriedUuidWhenIdSet);
217 }
218 self.controllee_uuid = uuid;
219 if uuid.is_some() {
220 self.cam.enable_controllee();
221 self.cam.set_controllee_id_format(IdFormat::Uuid128bit);
222 } else if self.controllee_id.is_none() {
223 self.cam.disable_controllee();
224 }
225 Ok(())
226 }
227
228 pub fn controller_uuid(&self) -> Option<u128> {
230 self.controller_uuid
231 }
232 pub fn set_controller_uuid(&mut self, uuid: Option<u128>) -> Result<(), VitaError> {
239 if uuid.is_some() && self.controller_id.is_some() {
240 return Err(VitaError::TriedUuidWhenIdSet);
241 }
242 self.controller_uuid = uuid;
243 if uuid.is_some() {
244 self.cam.enable_controller();
245 self.cam.set_controller_id_format(IdFormat::Uuid128bit);
246 } else if self.controller_id.is_none() {
247 self.cam.disable_controller();
248 }
249 Ok(())
250 }
251
252 pub fn payload(&self) -> &CommandPayload {
254 &self.command_payload
255 }
256
257 pub fn payload_mut(&mut self) -> &mut CommandPayload {
259 &mut self.command_payload
260 }
261
262 pub fn size_words(&self) -> u16 {
264 let mut ret = self.cam.size_words();
265 ret += 1; if self.controllee_id.is_some() {
267 ret += 1;
268 } else if self.controllee_uuid.is_some() {
269 ret += 4;
270 }
271 if self.controller_id.is_some() {
272 ret += 1;
273 } else if self.controller_uuid.is_some() {
274 ret += 4;
275 }
276 ret += self.command_payload.size_words();
277 ret
278 }
279}
280
281impl TryFrom<Payload> for Command {
282 type Error = Payload;
283
284 fn try_from(value: Payload) -> Result<Self, Self::Error> {
285 match value {
286 Payload::Command(c) => Ok(c),
287 a => Err(a),
288 }
289 }
290}
291
292impl fmt::Display for Command {
293 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
294 write!(f, "{}", self.cam)?;
295 writeln!(f, "Message ID: {:x}", self.message_id)?;
296 if let Some(cid) = self.controllee_id {
297 writeln!(f, "Controllee ID: {cid:x}")?;
298 }
299 if let Some(cuuid) = self.controllee_uuid {
300 writeln!(f, "Controllee UUID: {cuuid:x}")?;
301 }
302 if let Some(cid) = self.controller_id {
303 writeln!(f, "Controller ID: {cid:x}")?;
304 }
305 if let Some(cuuid) = self.controller_uuid {
306 writeln!(f, "Controller UUID: {cuuid:x}")?;
307 }
308 match &self.command_payload {
309 CommandPayload::Control(p) => write!(f, "{p}")?,
310 CommandPayload::Cancellation(p) => write!(f, "{p}")?,
311 CommandPayload::ValidationAck(p) => write!(f, "Validation {p}")?,
312 CommandPayload::ExecAck(p) => write!(f, "Execution {p}")?,
313 CommandPayload::QueryAck(p) => write!(f, "{p}")?,
314 };
315 Ok(())
316 }
317}
318
319#[cfg(test)]
320mod tests {
321 use crate::prelude::*;
322 use crate::{ActionMode, ControlAckMode, IdFormat, Tsf, Tsi};
323
324 #[test]
325 fn create_control_packet() {
326 let mut packet = Vrt::new_control_packet();
327 packet.set_stream_id(Some(0xDEADBEEF));
328 packet.set_integer_timestamp(Some(0), Tsi::Utc).unwrap();
329 packet
330 .set_fractional_timestamp(Some(0), Tsf::SampleCount)
331 .unwrap();
332 let command = packet.payload_mut().command_mut().unwrap();
333 command.set_message_id(123);
334 let mut cam = ControlAckMode::default();
335 cam.enable_controllee();
336 cam.enable_controller();
337 cam.set_controllee_id_format(IdFormat::Id32bit);
338 cam.set_controller_id_format(IdFormat::Uuid128bit);
339 cam.set_action_mode(ActionMode::Execute);
340 cam.set_partial_packet_impl_permitted();
341 cam.set_warnings_permitted();
342 cam.set_validation();
343 cam.set_warning();
344 cam.set_error();
345 command.set_cam(cam);
346 command.controllee_id = Some(123);
347 command.controller_uuid = Some(321);
348 }
349}