Implementation of firmware for a sprinklers system using async Rust, Tokio, Actix, MQTT and more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

106 lines
3.4 KiB

use super::*;
use sprinklers_actors::{program_runner::Error, state_manager::StateError};
use sprinklers_core::model::{ProgramId, ProgramRef, ProgramUpdateData};
use eyre::WrapErr;
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunProgramRequest {
program_id: ProgramId,
}
impl IRequest for RunProgramRequest {
type Response = ResponseMessage;
fn exec(self, ctx: &mut RequestContext) -> RequestFuture<Self::Response> {
let mut program_runner = ctx.program_runner.clone();
let program_id = self.program_id;
Box::pin(async move {
match program_runner.run_program_id(program_id).await {
Ok(program) => Ok(ResponseMessage::new(format!(
"running program '{}'",
program.name
))),
Err(e @ Error::InvalidProgramId(_)) => Err(RequestError::with_name(
ErrorCode::NoSuchProgram,
e,
"program",
)),
Err(e) => Err(e).wrap_err("could not run program")?,
}
})
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CancelProgramRequest {
program_id: ProgramId,
}
impl IRequest for CancelProgramRequest {
type Response = ResponseMessage;
fn exec(self, ctx: &mut RequestContext) -> RequestFuture<Self::Response> {
let mut program_runner = ctx.program_runner.clone();
let program_id = self.program_id;
Box::pin(async move {
let cancelled = program_runner
.cancel_program(program_id)
.await
.wrap_err("could not run cancel program")?;
match cancelled {
Some(program) => Ok(ResponseMessage::new(format!(
"program '{}' cancelled",
program.name
))),
None => Err(RequestError::with_name(
ErrorCode::NoSuchProgram,
"program was not running",
"program",
)),
}
})
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateProgramRequest {
program_id: ProgramId,
data: ProgramUpdateData,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateProgramResponse {
message: String,
data: ProgramRef,
}
impl IRequest for UpdateProgramRequest {
type Response = UpdateProgramResponse;
fn exec(self, ctx: &mut RequestContext) -> RequestFuture<Self::Response> {
let mut state_manager = ctx.state_manager.clone();
Box::pin(async move {
let new_program = state_manager
.update_program(self.program_id, self.data)
.await
.map_err(|err| match err {
e @ StateError::NoSuchProgram(_) => RequestError::with_name_and_cause(
ErrorCode::NoSuchProgram,
"could not update program",
"program",
e,
),
e => RequestError::from(eyre::Report::from(e)),
})?;
Ok(UpdateProgramResponse {
message: format!("updated program '{}'", new_program.name),
data: new_program,
})
})
}
}