1
1
use serde_json:: json;
2
- use tracing:: { error, trace, warn } ;
2
+ use tracing:: { error, trace} ;
3
3
use uuid:: Uuid ;
4
4
5
5
use crate :: device:: {
6
- manager :: { Answer , DeviceAnswer , ManagerError } ,
7
- manager:: { DeviceManager , DeviceSelection } ,
6
+ devices :: DeviceActorHandler ,
7
+ manager:: { Answer , DeviceAnswer , DeviceManager , DeviceSelection , ManagerError } ,
8
8
} ;
9
9
10
+ use super :: { DeviceProperties , Ping360Properties } ;
11
+
10
12
impl DeviceManager {
11
13
// Call the helpers specifically for each device type
12
14
pub async fn continuous_mode_start (
@@ -48,75 +50,29 @@ impl DeviceManager {
48
50
}
49
51
} ) ) ,
50
52
DeviceSelection :: Ping360 => {
51
- Some ( tokio:: spawn ( async move {
52
- // Attempt to send the Ping360 request and handle the result
53
- 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
- } ;
53
+ let device_properties = self . get_device_properties ( device_id) . await . ok ( ) ?;
54
+ let Some ( DeviceProperties :: Ping360 ( properties) ) = device_properties else {
55
+ error ! ( "No properties available for Ping360 device, device: {device_id}" ) ;
56
+ return None ;
57
+ } ;
75
58
76
- loop {
77
- for n in 0 ..=399 {
78
- // Handle timeout and errors
79
- 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
- } ) )
59
+ // Check if firmware supports auto-transmit mode
60
+ if properties. common . device_information . firmware_version_major >= 3
61
+ && properties. common . device_information . firmware_version_minor >= 3
62
+ {
63
+ Some ( Self :: start_ping360_firmware_mode (
64
+ handler,
65
+ device_id,
66
+ properties. clone ( ) ,
67
+ subscriber,
68
+ ) )
69
+ } else {
70
+ Some ( Self :: start_ping360_software_mode (
71
+ handler,
72
+ device_id,
73
+ properties. clone ( ) ,
74
+ ) )
75
+ }
120
76
}
121
77
DeviceSelection :: Common | DeviceSelection :: Auto => None ,
122
78
}
@@ -154,17 +110,33 @@ impl DeviceManager {
154
110
let handler_request = self . get_device_handler ( device_id) . await ?;
155
111
let handler = self . extract_handler ( handler_request) ?;
156
112
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) } ) ?;
113
+ match device_type {
114
+ DeviceSelection :: Ping1D => {
115
+ let id = <bluerobotics_ping:: ping1d:: ProfileStruct as bluerobotics_ping:: message:: MessageInfo >:: id ( ) ;
116
+ if let Err ( err) = handler
117
+ . send ( crate :: device:: devices:: PingRequest :: Ping1D (
118
+ crate :: device:: devices:: Ping1DRequest :: ContinuousStop (
119
+ bluerobotics_ping:: ping1d:: ContinuousStopStruct { id } ,
120
+ ) ,
121
+ ) )
122
+ . await
123
+ {
124
+ error ! ( "Something went wrong while executing continuous_mode_shutdown_routine, details: {err:?}, device: {device_id}" ) ;
125
+ }
126
+ }
127
+ DeviceSelection :: Ping360 => {
128
+ if let Err ( err) = handler
129
+ . send ( crate :: device:: devices:: PingRequest :: Ping360 (
130
+ crate :: device:: devices:: Ping360Request :: MotorOff ,
131
+ ) )
132
+ . await
133
+ {
134
+ error ! ( "Something went wrong while executing continuous_mode_shutdown_routine, details: {err:?}, device: {device_id}" ) ;
135
+ }
136
+ }
137
+ _ => { }
167
138
}
139
+
168
140
Ok ( ( ) )
169
141
}
170
142
@@ -177,7 +149,12 @@ impl DeviceManager {
177
149
if let Ok ( bluerobotics_ping:: Messages :: Ping1D ( bluerobotics_ping:: ping1d:: Messages :: Profile ( _answer) ) ) = bluerobotics_ping:: Messages :: try_from ( & msg) {
178
150
let answer = Answer :: DeviceMessage ( DeviceAnswer {
179
151
answer : crate :: device:: devices:: PingAnswer :: PingMessage (
180
- bluerobotics_ping:: Messages :: try_from ( & msg) . unwrap ( ) ,
152
+ match bluerobotics_ping:: Messages :: try_from ( & msg) {
153
+ Ok ( msg) => msg,
154
+ Err ( err) => {
155
+ error ! ( "Unexpected message during scan: {err:?}" ) ;
156
+ return } ,
157
+ }
181
158
) ,
182
159
device_id,
183
160
} ) ;
@@ -186,6 +163,29 @@ impl DeviceManager {
186
163
}
187
164
}
188
165
166
+ // An inner helper focused on Ping360 on AutoTransmit mode, which uses AutoDeviceData.
167
+ pub fn ping360_continuous_mode_helper_auto (
168
+ msg : bluerobotics_ping:: message:: ProtocolMessage ,
169
+ device_id : Uuid ,
170
+ ) {
171
+ if msg. message_id == <bluerobotics_ping:: ping360:: AutoDeviceDataStruct as bluerobotics_ping:: message:: MessageInfo >:: id ( ) {
172
+ if let Ok ( bluerobotics_ping:: Messages :: Ping360 ( bluerobotics_ping:: ping360:: Messages :: AutoDeviceData ( _answer) ) ) = bluerobotics_ping:: Messages :: try_from ( & msg) {
173
+ let answer = Answer :: DeviceMessage ( DeviceAnswer {
174
+ answer : crate :: device:: devices:: PingAnswer :: PingMessage (
175
+ match bluerobotics_ping:: Messages :: try_from ( & msg) {
176
+ Ok ( msg) => msg,
177
+ Err ( err) => {
178
+ error ! ( "Unexpected message during scan: {err:?}" ) ;
179
+ return } ,
180
+ }
181
+ ) ,
182
+ device_id,
183
+ } ) ;
184
+ crate :: server:: protocols:: v1:: websocket:: send_to_websockets ( json ! ( answer) , Some ( device_id) ) ;
185
+ }
186
+ }
187
+ }
188
+
189
189
// An inner helper focused on Ping360, which uses DeviceData message to plot graphs
190
190
pub fn ping360_continuous_mode_helper ( msg : bluerobotics_ping:: Messages , device_id : Uuid ) {
191
191
let answer = Answer :: DeviceMessage ( DeviceAnswer {
@@ -205,4 +205,195 @@ impl DeviceManager {
205
205
) ) ;
206
206
crate :: server:: protocols:: v1:: websocket:: send_to_websockets ( json ! ( error) , Some ( device_id) ) ;
207
207
}
208
+
209
+ fn start_ping360_firmware_mode (
210
+ handler : DeviceActorHandler ,
211
+ device_id : Uuid ,
212
+ properties : Ping360Properties ,
213
+ mut subscriber : tokio:: sync:: broadcast:: Receiver <
214
+ bluerobotics_ping:: message:: ProtocolMessage ,
215
+ > ,
216
+ ) -> tokio:: task:: JoinHandle < ( ) > {
217
+ tokio:: spawn ( async move {
218
+ loop {
219
+ let config = properties. continuous_mode_settings . clone ( ) ;
220
+ let initial_settings = match config. read ( ) {
221
+ Ok ( settings) => settings. clone ( ) ,
222
+ Err ( err) => {
223
+ error ! ( "Failed to read Ping360Config: {err:?}, device: {device_id}" ) ;
224
+ break ;
225
+ }
226
+ } ;
227
+
228
+ // Stop the motor before starting auto-transmit
229
+ if let Err ( err) = handler
230
+ . send ( crate :: device:: devices:: PingRequest :: Ping360 (
231
+ crate :: device:: devices:: Ping360Request :: MotorOff ,
232
+ ) )
233
+ . await
234
+ {
235
+ error ! ( "Failed to stop motor: {err:?}, device: {device_id}" ) ;
236
+ break ;
237
+ }
238
+
239
+ // Start auto-transmit mode
240
+ if let Err ( err) = handler
241
+ . send ( crate :: device:: devices:: PingRequest :: Ping360 (
242
+ crate :: device:: devices:: Ping360Request :: AutoTransmit (
243
+ bluerobotics_ping:: ping360:: AutoTransmitStruct {
244
+ mode : initial_settings. mode ,
245
+ gain_setting : initial_settings. gain_setting ,
246
+ transmit_duration : initial_settings. transmit_duration ,
247
+ sample_period : initial_settings. sample_period ,
248
+ transmit_frequency : initial_settings. transmit_frequency ,
249
+ number_of_samples : initial_settings. number_of_samples ,
250
+ start_angle : initial_settings. start_angle ,
251
+ stop_angle : initial_settings. stop_angle ,
252
+ num_steps : initial_settings. num_steps ,
253
+ delay : initial_settings. delay ,
254
+ } ,
255
+ ) ,
256
+ ) )
257
+ . await
258
+ {
259
+ error ! ( "Failed to start auto transmit: {err:?}, device: {device_id}" ) ;
260
+ break ;
261
+ }
262
+
263
+ loop {
264
+ let current_settings = match config. read ( ) {
265
+ Ok ( settings) => settings. clone ( ) ,
266
+ Err ( err) => {
267
+ error ! ( "Failed to read Ping360Config: {err:?}, device: {device_id}" ) ;
268
+ break ;
269
+ }
270
+ } ;
271
+ if initial_settings != current_settings {
272
+ break ;
273
+ }
274
+
275
+ match subscriber. recv ( ) . await {
276
+ Ok ( msg) => Self :: ping360_continuous_mode_helper_auto ( msg, device_id) ,
277
+ Err ( err) => {
278
+ Self :: handle_error_continuous_mode ( err, device_id) ;
279
+ return ;
280
+ }
281
+ }
282
+ }
283
+ }
284
+ } )
285
+ }
286
+
287
+ fn start_ping360_software_mode (
288
+ handler : DeviceActorHandler ,
289
+ device_id : Uuid ,
290
+ properties : Ping360Properties ,
291
+ ) -> tokio:: task:: JoinHandle < ( ) > {
292
+ tokio:: spawn ( async move {
293
+ loop {
294
+ let config = properties. continuous_mode_settings . clone ( ) ;
295
+ let initial_settings = match config. read ( ) {
296
+ Ok ( settings) => settings. clone ( ) ,
297
+ Err ( err) => {
298
+ error ! ( "Failed to read Ping360Config: {err:?}, device: {device_id}" ) ;
299
+ break ;
300
+ }
301
+ } ;
302
+
303
+ let mut angle = initial_settings. start_angle ;
304
+ let step_size = initial_settings. num_steps as u16 ;
305
+ let is_full_circle =
306
+ initial_settings. start_angle == 0 && initial_settings. stop_angle == 399 ;
307
+ let mut direction = 1i16 ;
308
+
309
+ loop {
310
+ let current_settings = match config. read ( ) {
311
+ Ok ( settings) => settings. clone ( ) ,
312
+ Err ( err) => {
313
+ error ! ( "Failed to read Ping360Config: {err:?}, device: {device_id}" ) ;
314
+ break ;
315
+ }
316
+ } ;
317
+ if initial_settings != current_settings {
318
+ break ;
319
+ }
320
+
321
+ match handler
322
+ . send ( crate :: device:: devices:: PingRequest :: Ping360 (
323
+ crate :: device:: devices:: Ping360Request :: Transducer (
324
+ bluerobotics_ping:: ping360:: TransducerStruct {
325
+ mode : initial_settings. mode ,
326
+ gain_setting : initial_settings. gain_setting ,
327
+ transmit_duration : initial_settings. transmit_duration ,
328
+ sample_period : initial_settings. sample_period ,
329
+ transmit_frequency : initial_settings. transmit_frequency ,
330
+ number_of_samples : initial_settings. number_of_samples ,
331
+ angle,
332
+ transmit : 1 ,
333
+ reserved : 0 ,
334
+ } ,
335
+ ) ,
336
+ ) )
337
+ . await
338
+ {
339
+ Ok ( answer) => match answer {
340
+ crate :: device:: devices:: PingAnswer :: PingMessage ( msg) => {
341
+ Self :: ping360_continuous_mode_helper ( msg, device_id)
342
+ }
343
+ msg => {
344
+ error ! ( "Unexpected message during scan: {msg:?}" ) ;
345
+ return ;
346
+ }
347
+ } ,
348
+ Err ( err) => {
349
+ error ! ( "Failed to send transducer command: {err:?}" ) ;
350
+ return ;
351
+ }
352
+ }
353
+
354
+ angle = Self :: calculate_next_angle (
355
+ angle,
356
+ step_size,
357
+ is_full_circle,
358
+ & mut direction,
359
+ initial_settings. start_angle ,
360
+ initial_settings. stop_angle ,
361
+ ) ;
362
+ }
363
+ }
364
+ } )
365
+ }
366
+
367
+ fn calculate_next_angle (
368
+ current_angle : u16 ,
369
+ step_size : u16 ,
370
+ is_full_circle : bool ,
371
+ direction : & mut i16 ,
372
+ start_angle : u16 ,
373
+ stop_angle : u16 ,
374
+ ) -> u16 {
375
+ if is_full_circle {
376
+ if current_angle + step_size >= 400 {
377
+ 0
378
+ } else {
379
+ current_angle + step_size
380
+ }
381
+ } else {
382
+ if * direction > 0 {
383
+ if current_angle + step_size > stop_angle {
384
+ * direction = -1 ;
385
+ stop_angle
386
+ } else {
387
+ current_angle + step_size
388
+ }
389
+ } else {
390
+ if ( current_angle as i32 - step_size as i32 ) <= start_angle as i32 {
391
+ * direction = 1 ;
392
+ start_angle
393
+ } else {
394
+ current_angle. wrapping_sub ( step_size)
395
+ }
396
+ }
397
+ }
398
+ }
208
399
}
0 commit comments