Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TS models for Vue [WIP] #5

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ udp-stream = "0.0.12"
uuid = { version = "1.8", features = ["serde"] }
validator = "0.18.1"
thiserror = "1.0.61"
ts-rs = { version = "9.0.1" , features = ["serde-compat", "uuid-impl"] }

[build-dependencies]
vergen-gix = { version = "1.0.0-beta.2", default-features = false, features = ["build", "cargo"] }
23 changes: 19 additions & 4 deletions src/device/devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use bluerobotics_ping::device::PingDevice;
use serde::{Deserialize, Serialize};
use tokio::sync::{mpsc, oneshot};
use tracing::{error, trace, warn};
use ts_rs::TS;

pub struct DeviceActor {
pub receiver: mpsc::Receiver<DeviceActorRequest>,
Expand Down Expand Up @@ -267,7 +268,7 @@ pub enum UpgradeResult {
Ping360,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
pub enum PingRequest {
Ping1D(Ping1DRequest),
Ping360(Ping360Request),
Expand All @@ -277,7 +278,7 @@ pub enum PingRequest {
Stop,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
pub enum Ping1DRequest {
DeviceID,
ModeAuto,
Expand All @@ -296,33 +297,47 @@ pub enum Ping1DRequest {
GainSetting,
PingEnable,
DistanceSimple,
#[ts(skip)]
SetDeviceId(bluerobotics_ping::ping1d::SetDeviceIdStruct),
#[ts(skip)]
SetModeAuto(bluerobotics_ping::ping1d::SetModeAutoStruct),
#[ts(skip)]
SetPingInterval(bluerobotics_ping::ping1d::SetPingIntervalStruct),
#[ts(skip)]
SetPingEnable(bluerobotics_ping::ping1d::SetPingEnableStruct),
#[ts(skip)]
SetSpeedOfSound(bluerobotics_ping::ping1d::SetSpeedOfSoundStruct),
#[ts(skip)]
SetRange(bluerobotics_ping::ping1d::SetRangeStruct),
#[ts(skip)]
SetGainSetting(bluerobotics_ping::ping1d::SetGainSettingStruct),
#[ts(skip)]
ContinuousStart(bluerobotics_ping::ping1d::ContinuousStartStruct),
#[ts(skip)]
ContinuousStop(bluerobotics_ping::ping1d::ContinuousStopStruct),
GotoBootloader,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
pub enum Ping360Request {
MotorOff,
DeviceData,
AutoDeviceData,
#[ts(skip)]
SetDeviceId(bluerobotics_ping::ping360::SetDeviceIdStruct),
#[ts(skip)]
Transducer(bluerobotics_ping::ping360::TransducerStruct),
#[ts(skip)]
Reset(bluerobotics_ping::ping360::ResetStruct),
#[ts(skip)]
AutoTransmit(bluerobotics_ping::ping360::AutoTransmitStruct),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
pub enum PingCommonRequest {
DeviceInformation,
ProtocolVersion,
#[ts(skip)]
SetDeviceId(bluerobotics_ping::common::SetDeviceIdStruct),
}

Expand Down
210 changes: 210 additions & 0 deletions src/device/helpers/continuous_mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
use serde_json::json;
use tracing::{error, trace, warn};
use uuid::Uuid;

use crate::device::{
manager::{Answer, DeviceAnswer, ManagerError},
manager::{DeviceManager, DeviceSelection},
};

impl DeviceManager {
// Call the helpers specifically for each device type
pub async fn continuous_mode_start(
&mut self,
mut subscriber: tokio::sync::broadcast::Receiver<
bluerobotics_ping::message::ProtocolMessage,
>,
device_id: Uuid,
device_type: DeviceSelection,
) -> Option<tokio::task::JoinHandle<()>> {
let raw_handler = match self.get_device_handler(device_id).await {
Ok(handler) => handler.clone(),
Err(err) => {
trace!("Error during start_continuous_mode: Failed to get device handler: {err:?}");
return None;
}
};

let handler = match self.extract_handler(raw_handler) {
Ok(handler) => handler,
Err(err) => {
trace!("Error during start_continuous_mode: Failed to extract handler: {err:?}");
return None;
}
};

match device_type {
DeviceSelection::Ping1D => Some(tokio::spawn(async move {
loop {
match subscriber.recv().await {
Ok(msg) => {
Self::ping1d_continuous_mode_helper(msg, device_id);
}
Err(err) => {
Self::handle_error_continuous_mode(err, device_id);
break;
}
}
}
})),
DeviceSelection::Ping360 => {
Some(tokio::spawn(async move {
let handler = handler.clone();

// Attempt to send the Ping360 request and handle the result
let device_data = match handler
.send(crate::device::devices::PingRequest::Ping360(
crate::device::devices::Ping360Request::DeviceData,
))
.await
{
Ok(response) => match response {
crate::device::devices::PingAnswer::PingMessage(
bluerobotics_ping::Messages::Ping360(
bluerobotics_ping::ping360::Messages::DeviceData(msg),
),
) => msg,
msg => {
error!("Error during start_continuous_mode: unexpected message: {msg:?}");
return;
}
},
Err(err) => {
error!("Error during start_continuous_mode: Device Error: {err:?}");
return;
}
};

loop {
for n in 0..399 {
// Handle timeout and errors
let result = tokio::time::timeout(
std::time::Duration::from_millis(1000),
handler.send(crate::device::devices::PingRequest::Ping360(
crate::device::devices::Ping360Request::Transducer(
bluerobotics_ping::ping360::TransducerStruct {
mode: device_data.mode,
gain_setting: device_data.gain_setting,
transmit_duration: device_data.transmit_duration,
sample_period: device_data.sample_period,
transmit_frequency: device_data.transmit_frequency,
number_of_samples: device_data.number_of_samples,
angle: n,
transmit: 1,
reserved: 0,
},
),
)),
)
.await;

match result {
Ok(Ok(answer)) => match answer {
crate::device::devices::PingAnswer::PingMessage(msg) => {
Self::ping360_continuous_mode_helper(msg, device_id)
}
msg => {
error!("Error during continuous_mode: Unexpected Message: {msg:?}");
return;
}
},
Ok(Err(err)) => {
error!("Error during continuous_mode: Device Error: {err:?}");
return;
}
Err(_err) => {
warn!("Error during continuous_mode: Answer delayed more than 1 s");
}
}
}
}
}))
}
DeviceSelection::Common | DeviceSelection::Auto => None,
}
}

// Execute some especial commands required for device enter in auto_send mode
pub async fn continuous_mode_startup_routine(
&self,
device_id: Uuid,
device_type: DeviceSelection,
) -> Result<(), ManagerError> {
if device_type == DeviceSelection::Ping1D {
let handler_request = self.get_device_handler(device_id).await?;
let handler = self.extract_handler(handler_request)?;

let id = <bluerobotics_ping::ping1d::ProfileStruct as bluerobotics_ping::message::MessageInfo>::id();
let _ = handler
.send(crate::device::devices::PingRequest::Ping1D(
crate::device::devices::Ping1DRequest::ContinuousStart(
bluerobotics_ping::ping1d::ContinuousStartStruct { id },
),
))
.await
.map_err(|err| {trace!("Something went wrong while executing continuous_mode_startup, details: {err:?}"); ManagerError::DeviceError(err)})?;
}
Ok(())
}

// Execute some especial commands required for device stop auto_send mode
pub async fn continuous_mode_shutdown_routine(
&self,
device_id: Uuid,
device_type: DeviceSelection,
) -> Result<(), ManagerError> {
let handler_request = self.get_device_handler(device_id).await?;
let handler = self.extract_handler(handler_request)?;

if device_type == DeviceSelection::Ping1D {
let id = <bluerobotics_ping::ping1d::ProfileStruct as bluerobotics_ping::message::MessageInfo>::id();
let _ = handler
.send(crate::device::devices::PingRequest::Ping1D(
crate::device::devices::Ping1DRequest::ContinuousStop(
bluerobotics_ping::ping1d::ContinuousStopStruct { id },
),
))
.await
.map_err(|err| {trace!("Something went wrong while executing broadcast_startup_routine, details: {err:?}"); ManagerError::DeviceError(err)})?;
}
Ok(())
}

// An inner helper focused on Ping1D, which uses Profile message to plot graphs
pub fn ping1d_continuous_mode_helper(
msg: bluerobotics_ping::message::ProtocolMessage,
device_id: Uuid,
) {
if msg.message_id == <bluerobotics_ping::ping1d::ProfileStruct as bluerobotics_ping::message::MessageInfo>::id() {
if let Ok(bluerobotics_ping::Messages::Ping1D(bluerobotics_ping::ping1d::Messages::Profile(_answer))) = bluerobotics_ping::Messages::try_from(&msg) {
let answer = Answer::DeviceMessage(DeviceAnswer {
answer: crate::device::devices::PingAnswer::PingMessage(
bluerobotics_ping::Messages::try_from(&msg).unwrap(),
),
device_id,
});
crate::server::protocols::v1::websocket::send_to_websockets(json!(answer), Some(device_id));
}
}
}

// An inner helper focused on Ping360, which uses DeviceData message to plot graphs
pub fn ping360_continuous_mode_helper(msg: bluerobotics_ping::Messages, device_id: Uuid) {
let answer = Answer::DeviceMessage(DeviceAnswer {
answer: crate::device::devices::PingAnswer::PingMessage(msg),
device_id,
});
crate::server::protocols::v1::websocket::send_to_websockets(json!(answer), Some(device_id));
}

// An inner helper that returns error to requester
pub fn handle_error_continuous_mode(
error: tokio::sync::broadcast::error::RecvError,
device_id: Uuid,
) {
let error = ManagerError::DeviceError(crate::device::devices::DeviceError::PingError(
bluerobotics_ping::error::PingError::TokioBroadcastError(error.to_string()),
));
crate::server::protocols::v1::websocket::send_to_websockets(json!(error), Some(device_id));
}
}
Loading
Loading