ping_viewer_next/device/
devices.rs

1use bluerobotics_ping::device::PingDevice;
2use paperclip::actix::Apiv2Schema;
3use serde::{Deserialize, Serialize};
4use tokio::sync::{mpsc, oneshot};
5use tracing::{error, trace, warn};
6
7pub struct DeviceActor {
8    pub receiver: mpsc::Receiver<DeviceActorRequest>,
9    pub device_type: DeviceType,
10}
11
12#[derive(Debug)]
13pub struct DeviceActorRequest {
14    pub request: PingRequest,
15    pub respond_to: oneshot::Sender<Result<PingAnswer, DeviceError>>,
16}
17
18impl DeviceActor {
19    async fn handle_message(&mut self, request: DeviceActorRequest) {
20        match request.request.clone() {
21            PingRequest::Ping1D(device_request) => match &self.device_type {
22                DeviceType::Ping1D(device) => {
23                    trace!("Handling Ping1D request: {device_request:?}");
24                    let answer = device.handle(device_request).await;
25                    let _ = request.respond_to.send(answer);
26                }
27                _ => {
28                    warn!(
29                        "Unsupported request for device type: {:?}",
30                        &self.device_type
31                    );
32                    let ping_request = request.request;
33                    let _ = request
34                        .respond_to
35                        .send(Ok(PingAnswer::NotSupported(ping_request)));
36                }
37            },
38            PingRequest::Ping360(device_request) => match &self.device_type {
39                DeviceType::Ping360(device) => {
40                    trace!("Handling Ping360 request: {device_request:?}");
41                    let answer = device.handle(device_request).await;
42                    let _ = request.respond_to.send(answer);
43                }
44                _ => {
45                    warn!(
46                        "Unsupported request for device type: {:?}",
47                        &self.device_type
48                    );
49                    let ping_request = request.request;
50                    let _ = request
51                        .respond_to
52                        .send(Ok(PingAnswer::NotSupported(ping_request)));
53                }
54            },
55            PingRequest::Common(device_request) => match &self.device_type {
56                DeviceType::Common(device) => {
57                    trace!("Handling Common request: {device_request:?}");
58                    let answer = device.handle(device_request).await;
59                    let _ = request.respond_to.send(answer);
60                }
61                DeviceType::Ping1D(device) => {
62                    trace!("Handling Common request: {device_request:?}");
63                    let answer = device.handle(device_request).await;
64                    let _ = request.respond_to.send(answer);
65                }
66                DeviceType::Ping360(device) => {
67                    trace!("Handling Common request: {device_request:?}");
68                    let answer = device.handle(device_request).await;
69                    let _ = request.respond_to.send(answer);
70                }
71                _ => {
72                    warn!(
73                        "Unsupported request for device type: {:?}",
74                        &self.device_type
75                    );
76                    let ping_request = request.request;
77                    let _ = request
78                        .respond_to
79                        .send(Ok(PingAnswer::NotSupported(ping_request)));
80                }
81            },
82            PingRequest::GetSubscriber => {
83                let answer = self.handle(request.request).await;
84                let _ = request.respond_to.send(Ok(answer));
85            }
86            PingRequest::Upgrade => {
87                let answer = self.try_upgrade().await;
88                let _ = request.respond_to.send(answer);
89            }
90            _ => todo!(),
91        }
92    }
93
94    pub async fn run(mut self) -> Self {
95        while let Some(msg) = self.receiver.recv().await {
96            match &msg.request {
97                PingRequest::Stop => {
98                    trace! {"Device received stop request, returning structure."}
99                    return self;
100                }
101                _ => self.handle_message(msg).await,
102            }
103        }
104        error! {"Device closed it's channel, returning structure."}
105        self
106    }
107
108    pub async fn try_upgrade(&mut self) -> Result<PingAnswer, DeviceError> {
109        let device_type_check = match &self.device_type {
110            DeviceType::Common(device) => {
111                let device_type_check = match device.device_information().await {
112                    Ok(result) => result.device_type,
113                    Err(e) => {
114                        return Err(DeviceError::PingError(e));
115                    }
116                };
117                if device_type_check == 0 {
118                    return Ok(PingAnswer::UpgradeResult(UpgradeResult::Unknown));
119                };
120                device_type_check
121            }
122            DeviceType::Ping1D(device) => {
123                let device_type_check = match device.device_information().await {
124                    Ok(result) => result.device_type,
125                    Err(e) => {
126                        return Err(DeviceError::PingError(e));
127                    }
128                };
129                if device_type_check == 1 {
130                    return Ok(PingAnswer::UpgradeResult(UpgradeResult::Ping1D));
131                };
132                device_type_check
133            }
134            DeviceType::Ping360(device) => {
135                let device_type_check = match device.device_information().await {
136                    Ok(result) => result.device_type,
137                    Err(e) => {
138                        return Err(DeviceError::PingError(e));
139                    }
140                };
141                if device_type_check == 2 {
142                    return Ok(PingAnswer::UpgradeResult(UpgradeResult::Ping360));
143                };
144                device_type_check
145            }
146            _ => {
147                todo!()
148            }
149        };
150
151        // Previous strategy tested and return fast if error/or already have the device upgraded,
152        // Otherwise it will be upgraded or return current structure.
153
154        // Helper function to create a new device type based on the type check
155        fn create_device_type(
156            common: bluerobotics_ping::device::Common,
157            device_type_check: u8,
158        ) -> DeviceType {
159            match device_type_check {
160                1 => DeviceType::Ping1D(bluerobotics_ping::ping1d::Device { common }),
161                2 => DeviceType::Ping360(bluerobotics_ping::ping360::Device { common }),
162                _ => DeviceType::Common(bluerobotics_ping::common::Device { common }),
163            }
164        }
165
166        // Strategy to manipulate self.device_type while matches the current value.
167        let placeholder = DeviceType::Null;
168        let device_type_tmp = std::mem::replace(&mut self.device_type, placeholder);
169
170        let upgrade_result = match device_type_check {
171            1 => UpgradeResult::Ping1D,
172            2 => UpgradeResult::Ping360,
173            _ => UpgradeResult::Unknown,
174        };
175
176        self.device_type = match device_type_tmp {
177            DeviceType::Common(device) => create_device_type(device.common, device_type_check),
178            DeviceType::Ping1D(device) => create_device_type(device.common, device_type_check),
179            DeviceType::Ping360(device) => create_device_type(device.common, device_type_check),
180            _ => {
181                // Unreachable.
182                self.device_type = device_type_tmp;
183                return Ok(PingAnswer::UpgradeResult(UpgradeResult::Unknown));
184            }
185        };
186
187        Ok(PingAnswer::UpgradeResult(upgrade_result))
188    }
189
190    pub fn new(device: DeviceType, size: usize) -> (Self, DeviceActorHandler) {
191        let (sender, receiver) = mpsc::channel(size);
192        let actor = DeviceActor {
193            receiver,
194            device_type: device,
195        };
196        let actor_handler = DeviceActorHandler { sender };
197
198        trace!("Device and handler successfully created: Success");
199        (actor, actor_handler)
200    }
201}
202
203#[derive(Clone, Debug)]
204pub struct DeviceActorHandler {
205    pub sender: mpsc::Sender<DeviceActorRequest>,
206}
207impl DeviceActorHandler {
208    pub async fn send(&self, device_request: PingRequest) -> Result<PingAnswer, DeviceError> {
209        let (result_sender, result_receiver) = oneshot::channel();
210
211        let device_request = DeviceActorRequest {
212            request: device_request,
213            respond_to: result_sender,
214        };
215
216        if let Err(err) = self.sender.send(device_request).await {
217            error!("DeviceManagerHandler: Failed to reach Device, details: {err:?}");
218            return Err(DeviceError::TokioError(err.to_string()));
219        }
220
221        match result_receiver
222            .await
223            .map_err(|err| DeviceError::TokioError(err.to_string()))
224        {
225            Ok(ans) => ans,
226            Err(err) => {
227                error!(
228                    "DeviceManagerHandler: Failed to receive message from Device, details: {err:?}"
229                );
230                Err(err)
231            }
232        }
233    }
234}
235
236#[derive(Debug, Serialize, Deserialize)]
237pub enum PingAnswer {
238    PingMessage(bluerobotics_ping::Messages),
239    NotSupported(PingRequest),
240    PingAcknowledge(PingRequest),
241    NotImplemented(PingRequest),
242    #[serde(skip)]
243    Subscriber(tokio::sync::broadcast::Receiver<bluerobotics_ping::message::ProtocolMessage>),
244    UpgradeResult(UpgradeResult),
245}
246
247#[derive(Debug, Serialize, Deserialize, Clone)]
248pub enum DeviceError {
249    PingError(bluerobotics_ping::error::PingError),
250    TokioError(String),
251}
252
253impl Clone for PingAnswer {
254    fn clone(&self) -> Self {
255        match self {
256            PingAnswer::PingMessage(msg) => PingAnswer::PingMessage(msg.clone()),
257            PingAnswer::NotSupported(req) => PingAnswer::NotSupported(req.clone()),
258            PingAnswer::PingAcknowledge(req) => PingAnswer::PingAcknowledge(req.clone()),
259            PingAnswer::NotImplemented(req) => PingAnswer::NotImplemented(req.clone()),
260            PingAnswer::Subscriber(receiver) => PingAnswer::Subscriber(receiver.resubscribe()),
261            PingAnswer::UpgradeResult(result) => PingAnswer::UpgradeResult(result.clone()),
262        }
263    }
264}
265
266#[derive(Debug)]
267pub enum DeviceType {
268    Common(bluerobotics_ping::common::Device),
269    Ping1D(bluerobotics_ping::device::Ping1D),
270    Ping360(bluerobotics_ping::device::Ping360),
271    Null,
272}
273
274#[derive(Debug, Serialize, Deserialize, Clone)]
275pub enum UpgradeResult {
276    Unknown,
277    Ping1D,
278    Ping360,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize, Apiv2Schema)]
282pub enum PingRequest {
283    Ping1D(Ping1DRequest),
284    Ping360(Ping360Request),
285    Common(PingCommonRequest),
286    GetSubscriber,
287    Upgrade,
288    Stop,
289}
290
291#[derive(Debug, Clone, Serialize, Deserialize, Apiv2Schema)]
292pub enum Ping1DRequest {
293    DeviceID,
294    ModeAuto,
295    Distance,
296    Profile,
297    SpeedOfSound,
298    Voltage5,
299    DeviceId,
300    FirmwareVersion,
301    Range,
302    TransmitDuration,
303    PingInterval,
304    ProcessorTemperature,
305    PcbTemperature,
306    GeneralInfo,
307    GainSetting,
308    PingEnable,
309    DistanceSimple,
310    SetDeviceId(bluerobotics_ping::ping1d::SetDeviceIdStruct),
311    SetModeAuto(bluerobotics_ping::ping1d::SetModeAutoStruct),
312    SetPingInterval(bluerobotics_ping::ping1d::SetPingIntervalStruct),
313    SetPingEnable(bluerobotics_ping::ping1d::SetPingEnableStruct),
314    SetSpeedOfSound(bluerobotics_ping::ping1d::SetSpeedOfSoundStruct),
315    SetRange(bluerobotics_ping::ping1d::SetRangeStruct),
316    SetGainSetting(bluerobotics_ping::ping1d::SetGainSettingStruct),
317    ContinuousStart(bluerobotics_ping::ping1d::ContinuousStartStruct),
318    ContinuousStop(bluerobotics_ping::ping1d::ContinuousStopStruct),
319    GotoBootloader,
320}
321
322#[derive(Debug, Clone, Serialize, Deserialize, Apiv2Schema)]
323pub enum Ping360Request {
324    MotorOff,
325    DeviceData,
326    AutoDeviceData,
327    SetDeviceId(bluerobotics_ping::ping360::SetDeviceIdStruct),
328    Transducer(bluerobotics_ping::ping360::TransducerStruct),
329    Reset(bluerobotics_ping::ping360::ResetStruct),
330    AutoTransmit(bluerobotics_ping::ping360::AutoTransmitStruct),
331}
332
333#[derive(Debug, Clone, Serialize, Deserialize, Apiv2Schema)]
334pub enum PingCommonRequest {
335    DeviceInformation,
336    ProtocolVersion,
337    SetDeviceId(bluerobotics_ping::common::SetDeviceIdStruct),
338}
339
340// All available requests are defined here for each
341trait Requests<T> {
342    type Reply;
343    async fn handle(&self, msg: T) -> Self::Reply;
344}
345
346impl Requests<Ping1DRequest> for bluerobotics_ping::device::Ping1D {
347    type Reply = Result<PingAnswer, DeviceError>;
348
349    async fn handle(&self, msg: Ping1DRequest) -> Self::Reply {
350        match &msg {
351            Ping1DRequest::DeviceID => match self.device_id().await {
352                Ok(result) => Ok(PingAnswer::PingMessage(
353                    bluerobotics_ping::Messages::Ping1D(
354                        bluerobotics_ping::ping1d::Messages::DeviceId(result),
355                    ),
356                )),
357                Err(e) => Err(DeviceError::PingError(e)),
358            },
359            Ping1DRequest::Distance => match self.distance().await {
360                Ok(result) => Ok(PingAnswer::PingMessage(
361                    bluerobotics_ping::Messages::Ping1D(
362                        bluerobotics_ping::ping1d::Messages::Distance(result),
363                    ),
364                )),
365                Err(e) => Err(DeviceError::PingError(e)),
366            },
367            Ping1DRequest::ModeAuto => match self.mode_auto().await {
368                Ok(result) => Ok(PingAnswer::PingMessage(
369                    bluerobotics_ping::Messages::Ping1D(
370                        bluerobotics_ping::ping1d::Messages::ModeAuto(result),
371                    ),
372                )),
373                Err(e) => Err(DeviceError::PingError(e)),
374            },
375            Ping1DRequest::Profile => match self.profile().await {
376                Ok(result) => Ok(PingAnswer::PingMessage(
377                    bluerobotics_ping::Messages::Ping1D(
378                        bluerobotics_ping::ping1d::Messages::Profile(result),
379                    ),
380                )),
381                Err(e) => Err(DeviceError::PingError(e)),
382            },
383            Ping1DRequest::SpeedOfSound => match self.speed_of_sound().await {
384                Ok(result) => Ok(PingAnswer::PingMessage(
385                    bluerobotics_ping::Messages::Ping1D(
386                        bluerobotics_ping::ping1d::Messages::SpeedOfSound(result),
387                    ),
388                )),
389                Err(e) => Err(DeviceError::PingError(e)),
390            },
391            Ping1DRequest::Voltage5 => match self.voltage_5().await {
392                Ok(result) => Ok(PingAnswer::PingMessage(
393                    bluerobotics_ping::Messages::Ping1D(
394                        bluerobotics_ping::ping1d::Messages::Voltage5(result),
395                    ),
396                )),
397                Err(e) => Err(DeviceError::PingError(e)),
398            },
399            Ping1DRequest::DeviceId => match self.device_id().await {
400                Ok(result) => Ok(PingAnswer::PingMessage(
401                    bluerobotics_ping::Messages::Ping1D(
402                        bluerobotics_ping::ping1d::Messages::DeviceId(result),
403                    ),
404                )),
405                Err(e) => Err(DeviceError::PingError(e)),
406            },
407            Ping1DRequest::FirmwareVersion => match self.firmware_version().await {
408                Ok(result) => Ok(PingAnswer::PingMessage(
409                    bluerobotics_ping::Messages::Ping1D(
410                        bluerobotics_ping::ping1d::Messages::FirmwareVersion(result),
411                    ),
412                )),
413                Err(e) => Err(DeviceError::PingError(e)),
414            },
415            Ping1DRequest::Range => match self.range().await {
416                Ok(result) => Ok(PingAnswer::PingMessage(
417                    bluerobotics_ping::Messages::Ping1D(
418                        bluerobotics_ping::ping1d::Messages::Range(result),
419                    ),
420                )),
421                Err(e) => Err(DeviceError::PingError(e)),
422            },
423            Ping1DRequest::TransmitDuration => match self.transmit_duration().await {
424                Ok(result) => Ok(PingAnswer::PingMessage(
425                    bluerobotics_ping::Messages::Ping1D(
426                        bluerobotics_ping::ping1d::Messages::TransmitDuration(result),
427                    ),
428                )),
429                Err(e) => Err(DeviceError::PingError(e)),
430            },
431            Ping1DRequest::PingInterval => match self.ping_interval().await {
432                Ok(result) => Ok(PingAnswer::PingMessage(
433                    bluerobotics_ping::Messages::Ping1D(
434                        bluerobotics_ping::ping1d::Messages::PingInterval(result),
435                    ),
436                )),
437                Err(e) => Err(DeviceError::PingError(e)),
438            },
439            Ping1DRequest::ProcessorTemperature => match self.processor_temperature().await {
440                Ok(result) => Ok(PingAnswer::PingMessage(
441                    bluerobotics_ping::Messages::Ping1D(
442                        bluerobotics_ping::ping1d::Messages::ProcessorTemperature(result),
443                    ),
444                )),
445                Err(e) => Err(DeviceError::PingError(e)),
446            },
447            Ping1DRequest::PcbTemperature => match self.pcb_temperature().await {
448                Ok(result) => Ok(PingAnswer::PingMessage(
449                    bluerobotics_ping::Messages::Ping1D(
450                        bluerobotics_ping::ping1d::Messages::PcbTemperature(result),
451                    ),
452                )),
453                Err(e) => Err(DeviceError::PingError(e)),
454            },
455            Ping1DRequest::GeneralInfo => match self.general_info().await {
456                Ok(result) => Ok(PingAnswer::PingMessage(
457                    bluerobotics_ping::Messages::Ping1D(
458                        bluerobotics_ping::ping1d::Messages::GeneralInfo(result),
459                    ),
460                )),
461                Err(e) => Err(DeviceError::PingError(e)),
462            },
463            Ping1DRequest::GainSetting => match self.gain_setting().await {
464                Ok(result) => Ok(PingAnswer::PingMessage(
465                    bluerobotics_ping::Messages::Ping1D(
466                        bluerobotics_ping::ping1d::Messages::GainSetting(result),
467                    ),
468                )),
469                Err(e) => Err(DeviceError::PingError(e)),
470            },
471            Ping1DRequest::PingEnable => match self.ping_enable().await {
472                Ok(result) => Ok(PingAnswer::PingMessage(
473                    bluerobotics_ping::Messages::Ping1D(
474                        bluerobotics_ping::ping1d::Messages::PingEnable(result),
475                    ),
476                )),
477                Err(e) => Err(DeviceError::PingError(e)),
478            },
479            Ping1DRequest::DistanceSimple => match self.distance_simple().await {
480                Ok(result) => Ok(PingAnswer::PingMessage(
481                    bluerobotics_ping::Messages::Ping1D(
482                        bluerobotics_ping::ping1d::Messages::DistanceSimple(result),
483                    ),
484                )),
485                Err(e) => Err(DeviceError::PingError(e)),
486            },
487            Ping1DRequest::SetDeviceId(req_body) => {
488                match self.set_device_id(req_body.device_id).await {
489                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
490                    Err(e) => Err(DeviceError::PingError(e)),
491                }
492            }
493            Ping1DRequest::ContinuousStart(req_body) => {
494                match self.continuous_start(req_body.id).await {
495                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
496                    Err(e) => Err(DeviceError::PingError(e)),
497                }
498            }
499            Ping1DRequest::ContinuousStop(req_body) => {
500                match self.continuous_stop(req_body.id).await {
501                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
502                    Err(e) => Err(DeviceError::PingError(e)),
503                }
504            }
505            Ping1DRequest::SetModeAuto(req_body) => {
506                match self.set_mode_auto(req_body.mode_auto).await {
507                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
508                    Err(e) => Err(DeviceError::PingError(e)),
509                }
510            }
511            Ping1DRequest::SetPingInterval(req_body) => {
512                match self.set_ping_interval(req_body.ping_interval).await {
513                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
514                    Err(e) => Err(DeviceError::PingError(e)),
515                }
516            }
517            Ping1DRequest::SetPingEnable(req_body) => {
518                match self.set_ping_enable(req_body.ping_enabled).await {
519                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
520                    Err(e) => Err(DeviceError::PingError(e)),
521                }
522            }
523            Ping1DRequest::SetSpeedOfSound(req_body) => {
524                match self.set_speed_of_sound(req_body.speed_of_sound).await {
525                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
526                    Err(e) => Err(DeviceError::PingError(e)),
527                }
528            }
529            Ping1DRequest::SetRange(req_body) => {
530                match self
531                    .set_range(req_body.scan_start, req_body.scan_length)
532                    .await
533                {
534                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
535                    Err(e) => Err(DeviceError::PingError(e)),
536                }
537            }
538            Ping1DRequest::SetGainSetting(req_body) => {
539                match self.set_gain_setting(req_body.gain_setting).await {
540                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
541                    Err(e) => Err(DeviceError::PingError(e)),
542                }
543            }
544            Ping1DRequest::GotoBootloader => match self.goto_bootloader().await {
545                Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping1D(msg))),
546                Err(e) => Err(DeviceError::PingError(e)),
547            },
548        }
549    }
550}
551
552impl Requests<Ping360Request> for bluerobotics_ping::device::Ping360 {
553    type Reply = Result<PingAnswer, DeviceError>;
554
555    async fn handle(&self, msg: Ping360Request) -> Self::Reply {
556        match &msg {
557            Ping360Request::MotorOff => match self.motor_off().await {
558                Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping360(msg))),
559                Err(e) => Err(DeviceError::PingError(e)),
560            },
561            Ping360Request::AutoDeviceData => match self.auto_device_data().await {
562                Ok(answer) => Ok(PingAnswer::PingMessage(
563                    bluerobotics_ping::Messages::Ping360(
564                        bluerobotics_ping::ping360::Messages::AutoDeviceData(answer),
565                    ),
566                )),
567                Err(e) => Err(DeviceError::PingError(e)),
568            },
569            Ping360Request::DeviceData => match self.device_data().await {
570                Ok(answer) => Ok(PingAnswer::PingMessage(
571                    bluerobotics_ping::Messages::Ping360(
572                        bluerobotics_ping::ping360::Messages::DeviceData(answer),
573                    ),
574                )),
575                Err(e) => Err(DeviceError::PingError(e)),
576            },
577            Ping360Request::SetDeviceId(req_body) => {
578                match self.set_device_id(req_body.id, req_body.reserved).await {
579                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping360(msg))),
580                    Err(e) => Err(DeviceError::PingError(e)),
581                }
582            }
583            Ping360Request::Reset(req_body) => {
584                match self.reset(req_body.bootloader, req_body.reserved).await {
585                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping360(msg))),
586                    Err(e) => Err(DeviceError::PingError(e)),
587                }
588            }
589            Ping360Request::AutoTransmit(req_body) => {
590                match self
591                    .auto_transmit(
592                        req_body.mode,
593                        req_body.gain_setting,
594                        req_body.transmit_duration,
595                        req_body.sample_period,
596                        req_body.transmit_frequency,
597                        req_body.number_of_samples,
598                        req_body.start_angle,
599                        req_body.stop_angle,
600                        req_body.num_steps,
601                        req_body.delay,
602                    )
603                    .await
604                {
605                    Ok(_) => Ok(PingAnswer::PingAcknowledge(PingRequest::Ping360(msg))),
606                    Err(e) => Err(DeviceError::PingError(e)),
607                }
608            }
609            Ping360Request::Transducer(req_body) => {
610                match self
611                    .transducer(
612                        req_body.mode,
613                        req_body.gain_setting,
614                        req_body.angle,
615                        req_body.transmit_duration,
616                        req_body.sample_period,
617                        req_body.transmit_frequency,
618                        req_body.number_of_samples,
619                        req_body.transmit,
620                        req_body.reserved,
621                    )
622                    .await
623                {
624                    Ok(answer) => Ok(PingAnswer::PingMessage(
625                        bluerobotics_ping::Messages::Ping360(
626                            bluerobotics_ping::ping360::Messages::DeviceData(answer),
627                        ),
628                    )),
629                    Err(e) => Err(DeviceError::PingError(e)),
630                }
631            }
632        }
633    }
634}
635
636impl Requests<PingCommonRequest> for bluerobotics_ping::common::Device {
637    type Reply = Result<PingAnswer, DeviceError>;
638
639    async fn handle(&self, msg: PingCommonRequest) -> Self::Reply {
640        match &msg {
641            PingCommonRequest::ProtocolVersion => match self.protocol_version().await {
642                Ok(result) => Ok(PingAnswer::PingMessage(
643                    bluerobotics_ping::Messages::Common(
644                        bluerobotics_ping::common::Messages::ProtocolVersion(result),
645                    ),
646                )),
647                Err(e) => Err(DeviceError::PingError(e)),
648            },
649            PingCommonRequest::DeviceInformation => match self.device_information().await {
650                Ok(result) => Ok(PingAnswer::PingMessage(
651                    bluerobotics_ping::Messages::Common(
652                        bluerobotics_ping::common::Messages::DeviceInformation(result),
653                    ),
654                )),
655                Err(e) => Err(DeviceError::PingError(e)),
656            },
657            _ => Ok(PingAnswer::NotImplemented(PingRequest::Common(msg))),
658        }
659    }
660}
661
662impl Requests<PingCommonRequest> for bluerobotics_ping::ping1d::Device {
663    type Reply = Result<PingAnswer, DeviceError>;
664
665    async fn handle(&self, msg: PingCommonRequest) -> Self::Reply {
666        match &msg {
667            PingCommonRequest::ProtocolVersion => match self.protocol_version().await {
668                Ok(result) => Ok(PingAnswer::PingMessage(
669                    bluerobotics_ping::Messages::Common(
670                        bluerobotics_ping::common::Messages::ProtocolVersion(result),
671                    ),
672                )),
673                Err(e) => Err(DeviceError::PingError(e)),
674            },
675            PingCommonRequest::DeviceInformation => match self.device_information().await {
676                Ok(result) => Ok(PingAnswer::PingMessage(
677                    bluerobotics_ping::Messages::Common(
678                        bluerobotics_ping::common::Messages::DeviceInformation(result),
679                    ),
680                )),
681                Err(e) => Err(DeviceError::PingError(e)),
682            },
683            _ => Ok(PingAnswer::NotImplemented(PingRequest::Common(msg))),
684        }
685    }
686}
687
688impl Requests<PingCommonRequest> for bluerobotics_ping::ping360::Device {
689    type Reply = Result<PingAnswer, DeviceError>;
690
691    async fn handle(&self, msg: PingCommonRequest) -> Self::Reply {
692        match &msg {
693            PingCommonRequest::ProtocolVersion => match self.protocol_version().await {
694                Ok(result) => Ok(PingAnswer::PingMessage(
695                    bluerobotics_ping::Messages::Common(
696                        bluerobotics_ping::common::Messages::ProtocolVersion(result),
697                    ),
698                )),
699                Err(e) => Err(DeviceError::PingError(e)),
700            },
701            PingCommonRequest::DeviceInformation => match self.device_information().await {
702                Ok(result) => Ok(PingAnswer::PingMessage(
703                    bluerobotics_ping::Messages::Common(
704                        bluerobotics_ping::common::Messages::DeviceInformation(result),
705                    ),
706                )),
707                Err(e) => Err(DeviceError::PingError(e)),
708            },
709            _ => Ok(PingAnswer::NotImplemented(PingRequest::Common(msg))),
710        }
711    }
712}
713
714impl Requests<PingRequest> for DeviceActor {
715    type Reply = PingAnswer;
716    async fn handle(&self, msg: PingRequest) -> Self::Reply {
717        match &msg {
718            PingRequest::GetSubscriber => match &self.device_type {
719                DeviceType::Common(_) => PingAnswer::NotSupported(msg),
720                DeviceType::Ping1D(device) => PingAnswer::Subscriber(device.subscribe()),
721                DeviceType::Ping360(device) => PingAnswer::Subscriber(device.subscribe()),
722                _ => todo!(),
723            },
724            PingRequest::Upgrade => todo!(),
725            PingRequest::Stop => todo!(),
726
727            _ => PingAnswer::NotSupported(msg),
728        }
729    }
730}