move cmd off of grpc
This commit is contained in:
@@ -1,78 +1,36 @@
|
||||
use chrono::DateTime;
|
||||
use server::core::client_side_command::Inner;
|
||||
use server::core::command_service_client::CommandServiceClient;
|
||||
use server::core::telemetry_value::Value;
|
||||
use server::core::{
|
||||
ClientSideCommand, Command, CommandDefinitionRequest, CommandParameterDefinition,
|
||||
CommandResponse, TelemetryDataType,
|
||||
use anyhow::anyhow;
|
||||
use api::client::Client;
|
||||
use api::data_type::DataType;
|
||||
use api::messages::command::{
|
||||
Command, CommandDefinition, CommandParameterDefinition, CommandResponse,
|
||||
};
|
||||
use std::error::Error;
|
||||
use tokio::select;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::task::JoinHandle;
|
||||
use std::sync::Arc;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tonic::codegen::tokio_stream::wrappers::ReceiverStream;
|
||||
use tonic::codegen::tokio_stream::StreamExt;
|
||||
use tonic::transport::Channel;
|
||||
|
||||
struct CommandHandler {
|
||||
handle: JoinHandle<()>,
|
||||
}
|
||||
fn handle_command(command: Command) -> anyhow::Result<String> {
|
||||
let timestamp = command.timestamp;
|
||||
let a: f32 = (*command
|
||||
.parameters
|
||||
.get("a")
|
||||
.ok_or(anyhow!("Parameter 'a' Missing"))?)
|
||||
.try_into()?;
|
||||
let b: f64 = (*command
|
||||
.parameters
|
||||
.get("b")
|
||||
.ok_or(anyhow!("Parameter 'b' Missing"))?)
|
||||
.try_into()?;
|
||||
let c: bool = (*command
|
||||
.parameters
|
||||
.get("c")
|
||||
.ok_or(anyhow!("Parameter 'c' Missing"))?)
|
||||
.try_into()?;
|
||||
|
||||
impl CommandHandler {
|
||||
pub async fn new<F: Fn(Command) -> CommandResponse + Send + 'static>(
|
||||
cancellation_token: CancellationToken,
|
||||
client: &mut CommandServiceClient<Channel>,
|
||||
command_definition_request: CommandDefinitionRequest,
|
||||
handler: F,
|
||||
) -> anyhow::Result<Self> {
|
||||
let (tx, rx) = mpsc::channel(4);
|
||||
println!("Command Received:\n timestamp: {timestamp}\n a: {a}\n b: {b}\n c: {c}");
|
||||
|
||||
// The buffer size of 4 means this is safe to send immediately
|
||||
tx.send(ClientSideCommand {
|
||||
inner: Some(Inner::Request(command_definition_request)),
|
||||
})
|
||||
.await?;
|
||||
let response = client.new_command(ReceiverStream::new(rx)).await?;
|
||||
let mut cmd_stream = response.into_inner();
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
loop {
|
||||
select! {
|
||||
_ = cancellation_token.cancelled() => break,
|
||||
Some(msg) = cmd_stream.next() => {
|
||||
match msg {
|
||||
Ok(cmd) => {
|
||||
let uuid = cmd.uuid.clone();
|
||||
let mut response = handler(cmd);
|
||||
response.uuid = uuid;
|
||||
match tx.send(ClientSideCommand {
|
||||
inner: Some(Inner::Response(response))
|
||||
}).await {
|
||||
Ok(()) => {},
|
||||
Err(e) => {
|
||||
println!("SendError: {e}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error: {e}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
else => break,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Self { handle })
|
||||
}
|
||||
|
||||
pub async fn join(self) -> anyhow::Result<()> {
|
||||
Ok(self.handle.await?)
|
||||
}
|
||||
Ok(format!(
|
||||
"Successfully Received Command! timestamp: {timestamp} a: {a} b: {b} c: {c}"
|
||||
))
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@@ -86,56 +44,41 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
});
|
||||
}
|
||||
|
||||
let mut client = CommandServiceClient::connect("http://[::1]:50051").await?;
|
||||
let client = Arc::new(Client::connect("ws://[::1]:8080/backend")?);
|
||||
|
||||
let cmd_handler = CommandHandler::new(
|
||||
cancellation_token,
|
||||
&mut client,
|
||||
CommandDefinitionRequest {
|
||||
name: "simple_command/a".to_string(),
|
||||
parameters: vec![
|
||||
CommandParameterDefinition {
|
||||
name: "a".to_string(),
|
||||
data_type: TelemetryDataType::Float32.into(),
|
||||
client
|
||||
.register_callback_fn(
|
||||
CommandDefinition {
|
||||
name: "simple_command/a".to_string(),
|
||||
parameters: vec![
|
||||
CommandParameterDefinition {
|
||||
name: "a".to_string(),
|
||||
data_type: DataType::Float32,
|
||||
},
|
||||
CommandParameterDefinition {
|
||||
name: "b".to_string(),
|
||||
data_type: DataType::Float64,
|
||||
},
|
||||
CommandParameterDefinition {
|
||||
name: "c".to_string(),
|
||||
data_type: DataType::Boolean,
|
||||
},
|
||||
],
|
||||
},
|
||||
|command| match handle_command(command) {
|
||||
Ok(response) => CommandResponse {
|
||||
success: true,
|
||||
response,
|
||||
},
|
||||
CommandParameterDefinition {
|
||||
name: "b".to_string(),
|
||||
data_type: TelemetryDataType::Float64.into(),
|
||||
Err(error) => CommandResponse {
|
||||
success: false,
|
||||
response: error.to_string(),
|
||||
},
|
||||
CommandParameterDefinition {
|
||||
name: "c".to_string(),
|
||||
data_type: TelemetryDataType::Boolean.into(),
|
||||
},
|
||||
],
|
||||
},
|
||||
|command| {
|
||||
let timestamp = command.timestamp.expect("Missing Timestamp");
|
||||
let timestamp = DateTime::from_timestamp(timestamp.secs, timestamp.nanos as u32)
|
||||
.expect("Could not construct date time");
|
||||
let Value::Float32(a) = command.parameters["a"].value.expect("Missing Value a") else {
|
||||
panic!("Wrong Type a");
|
||||
};
|
||||
let Value::Float64(b) = command.parameters["b"].value.expect("Missing Value b") else {
|
||||
panic!("Wrong Type b");
|
||||
};
|
||||
let Value::Boolean(c) = command.parameters["c"].value.expect("Missing Value c") else {
|
||||
panic!("Wrong Type c");
|
||||
};
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
println!("Command Received:\n timestamp: {timestamp}\n a: {a}\n b: {b}\n c: {c}");
|
||||
|
||||
CommandResponse {
|
||||
uuid: command.uuid.clone(),
|
||||
success: true,
|
||||
response: format!(
|
||||
"Successfully Received Command! timestamp: {timestamp} a: {a} b: {b} c: {c}"
|
||||
),
|
||||
}
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
cmd_handler.join().await?;
|
||||
cancellation_token.cancelled().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user