ping_viewer_next/device/manager/
continuous_mode.rs1use serde_json::json;
2use tracing::{error, trace, warn};
3use uuid::Uuid;
4
5use crate::device::{
6 manager::{Answer, DeviceAnswer, ManagerError},
7 manager::{DeviceManager, DeviceSelection},
8};
9
10impl DeviceManager {
11 pub async fn continuous_mode_start(
13 &mut self,
14 mut subscriber: tokio::sync::broadcast::Receiver<
15 bluerobotics_ping::message::ProtocolMessage,
16 >,
17 device_id: Uuid,
18 device_type: DeviceSelection,
19 ) -> Option<tokio::task::JoinHandle<()>> {
20 let raw_handler = match self.get_device_handler(device_id).await {
21 Ok(handler) => handler,
22 Err(err) => {
23 trace!("Error during start_continuous_mode: Failed to get device handler: {err:?}");
24 return None;
25 }
26 };
27
28 let handler = match self.extract_handler(raw_handler) {
29 Ok(handler) => handler,
30 Err(err) => {
31 trace!("Error during start_continuous_mode: Failed to extract handler: {err:?}");
32 return None;
33 }
34 };
35
36 match device_type {
37 DeviceSelection::Ping1D => Some(tokio::spawn(async move {
38 loop {
39 match subscriber.recv().await {
40 Ok(msg) => {
41 Self::ping1d_continuous_mode_helper(msg, device_id);
42 }
43 Err(err) => {
44 Self::handle_error_continuous_mode(err, device_id);
45 break;
46 }
47 }
48 }
49 })),
50 DeviceSelection::Ping360 => {
51 Some(tokio::spawn(async move {
52 let device_data = match handler
54 .send(crate::device::devices::PingRequest::Ping360(
55 crate::device::devices::Ping360Request::DeviceData,
56 ))
57 .await
58 {
59 Ok(response) => match response {
60 crate::device::devices::PingAnswer::PingMessage(
61 bluerobotics_ping::Messages::Ping360(
62 bluerobotics_ping::ping360::Messages::DeviceData(msg),
63 ),
64 ) => msg,
65 msg => {
66 error!("Error during start_continuous_mode: unexpected message: {msg:?}");
67 return;
68 }
69 },
70 Err(err) => {
71 error!("Error during start_continuous_mode: Device Error: {err:?}");
72 return;
73 }
74 };
75
76 loop {
77 for n in 0..=399 {
78 let result = tokio::time::timeout(
80 std::time::Duration::from_millis(1000),
81 handler.send(crate::device::devices::PingRequest::Ping360(
82 crate::device::devices::Ping360Request::Transducer(
83 bluerobotics_ping::ping360::TransducerStruct {
84 mode: device_data.mode,
85 gain_setting: device_data.gain_setting,
86 transmit_duration: device_data.transmit_duration,
87 sample_period: device_data.sample_period,
88 transmit_frequency: device_data.transmit_frequency,
89 number_of_samples: device_data.number_of_samples,
90 angle: n,
91 transmit: 1,
92 reserved: 0,
93 },
94 ),
95 )),
96 )
97 .await;
98
99 match result {
100 Ok(Ok(answer)) => match answer {
101 crate::device::devices::PingAnswer::PingMessage(msg) => {
102 Self::ping360_continuous_mode_helper(msg, device_id)
103 }
104 msg => {
105 error!("Error during continuous_mode: Unexpected Message: {msg:?}");
106 return;
107 }
108 },
109 Ok(Err(err)) => {
110 error!("Error during continuous_mode: Device Error: {err:?}");
111 return;
112 }
113 Err(_err) => {
114 warn!("Error during continuous_mode: Answer delayed more than 1 s");
115 }
116 }
117 }
118 }
119 }))
120 }
121 DeviceSelection::Common | DeviceSelection::Auto => None,
122 }
123 }
124
125 pub async fn continuous_mode_startup_routine(
127 &self,
128 device_id: Uuid,
129 device_type: DeviceSelection,
130 ) -> Result<(), ManagerError> {
131 if device_type == DeviceSelection::Ping1D {
132 let handler_request = self.get_device_handler(device_id).await?;
133 let handler = self.extract_handler(handler_request)?;
134
135 let id = <bluerobotics_ping::ping1d::ProfileStruct as bluerobotics_ping::message::MessageInfo>::id();
136 let _ = handler
137 .send(crate::device::devices::PingRequest::Ping1D(
138 crate::device::devices::Ping1DRequest::ContinuousStart(
139 bluerobotics_ping::ping1d::ContinuousStartStruct { id },
140 ),
141 ))
142 .await
143 .map_err(|err| {trace!("Something went wrong while executing continuous_mode_startup, details: {err:?}"); ManagerError::DeviceError(err)})?;
144 }
145 Ok(())
146 }
147
148 pub async fn continuous_mode_shutdown_routine(
150 &self,
151 device_id: Uuid,
152 device_type: DeviceSelection,
153 ) -> Result<(), ManagerError> {
154 let handler_request = self.get_device_handler(device_id).await?;
155 let handler = self.extract_handler(handler_request)?;
156
157 if device_type == DeviceSelection::Ping1D {
158 let id = <bluerobotics_ping::ping1d::ProfileStruct as bluerobotics_ping::message::MessageInfo>::id();
159 let _ = handler
160 .send(crate::device::devices::PingRequest::Ping1D(
161 crate::device::devices::Ping1DRequest::ContinuousStop(
162 bluerobotics_ping::ping1d::ContinuousStopStruct { id },
163 ),
164 ))
165 .await
166 .map_err(|err| {trace!("Something went wrong while executing broadcast_startup_routine, details: {err:?}"); ManagerError::DeviceError(err)})?;
167 }
168 Ok(())
169 }
170
171 pub fn ping1d_continuous_mode_helper(
173 msg: bluerobotics_ping::message::ProtocolMessage,
174 device_id: Uuid,
175 ) {
176 if msg.message_id == <bluerobotics_ping::ping1d::ProfileStruct as bluerobotics_ping::message::MessageInfo>::id() {
177 if let Ok(bluerobotics_ping::Messages::Ping1D(bluerobotics_ping::ping1d::Messages::Profile(_answer))) = bluerobotics_ping::Messages::try_from(&msg) {
178 let answer = Answer::DeviceMessage(DeviceAnswer {
179 answer: crate::device::devices::PingAnswer::PingMessage(
180 bluerobotics_ping::Messages::try_from(&msg).unwrap(),
181 ),
182 device_id,
183 });
184 crate::server::protocols::v1::websocket::send_to_websockets(json!(answer), Some(device_id));
185 }
186 }
187 }
188
189 pub fn ping360_continuous_mode_helper(msg: bluerobotics_ping::Messages, device_id: Uuid) {
191 let answer = Answer::DeviceMessage(DeviceAnswer {
192 answer: crate::device::devices::PingAnswer::PingMessage(msg),
193 device_id,
194 });
195 crate::server::protocols::v1::websocket::send_to_websockets(json!(answer), Some(device_id));
196 }
197
198 pub fn handle_error_continuous_mode(
200 error: tokio::sync::broadcast::error::RecvError,
201 device_id: Uuid,
202 ) {
203 let error = ManagerError::DeviceError(crate::device::devices::DeviceError::PingError(
204 bluerobotics_ping::error::PingError::TokioBroadcastError(error.to_string()),
205 ));
206 crate::server::protocols::v1::websocket::send_to_websockets(json!(error), Some(device_id));
207 }
208}