use pydantic instead of serde in Python

This commit is contained in:
2024-04-28 12:39:34 +02:00
parent 14aa2f39a5
commit 56b5076230
11 changed files with 130 additions and 131 deletions

View File

@ -1,4 +1,3 @@
use crate::pus::action::send_data_reply;
/// Device handler implementation for the IMS-100 Imager used on the OPS-SAT mission.
///
/// from the [OPSSAT Experimenter Wiki](https://opssat1.esoc.esa.int/projects/experimenter-information/wiki/Camera_Introduction):
@ -25,9 +24,11 @@ use crate::pus::action::send_data_reply;
/// v Y
///
/// see also https://opssat1.esoc.esa.int/dmsf/files/6/view
use crate::pus::action::send_data_reply;
use crate::requests::CompositeRequest;
use derive_new::new;
use log::{debug, info};
use num_enum::TryFromPrimitive;
use ops_sat_rs::TimeStampHelper;
use satrs::action::{ActionRequest, ActionRequestVariant};
use satrs::hk::HkRequest;
@ -88,8 +89,9 @@ const BALANCED_SINGLE_FLATSAT_CAM_PARAMS: CameraPictureParameters = CameraPictur
// TODO ls -l via cfdp
// TODO howto downlink
#[derive(Debug)]
pub enum CameraActionId {
#[derive(Debug, TryFromPrimitive)]
#[repr(u32)]
pub enum ActionId {
DefaultSingle = 1,
BalancedSingle = 2,
DefaultSingleFlatSat = 3,
@ -97,31 +99,6 @@ pub enum CameraActionId {
CustomParameters = 5,
}
impl TryFrom<u32> for CameraActionId {
type Error = ();
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
value if value == CameraActionId::DefaultSingle as u32 => {
Ok(CameraActionId::DefaultSingle)
}
value if value == CameraActionId::BalancedSingle as u32 => {
Ok(CameraActionId::BalancedSingle)
}
value if value == CameraActionId::DefaultSingleFlatSat as u32 => {
Ok(CameraActionId::DefaultSingleFlatSat)
}
value if value == CameraActionId::BalancedSingleFlatSat as u32 => {
Ok(CameraActionId::BalancedSingleFlatSat)
}
value if value == CameraActionId::CustomParameters as u32 => {
Ok(CameraActionId::CustomParameters)
}
_ => Err(()),
}
}
}
// TODO what happens if limits are exceded
#[allow(non_snake_case)]
#[derive(Debug, Serialize, Deserialize, new)]
@ -189,11 +166,9 @@ impl fmt::Display for CameraError {
#[allow(dead_code)]
#[derive(Debug)]
pub struct IMS100BatchHandler {
pub struct Ims100BatchHandler {
id: UniqueApidTargetId,
// mode_interface: MpscModeLeafInterface,
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
// hk_reply_sender: mpsc::Sender<GenericMessage<HkReply>>,
tm_tx: mpsc::Sender<PacketAsVec>,
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
stamp_helper: TimeStampHelper,
@ -201,7 +176,7 @@ pub struct IMS100BatchHandler {
#[allow(non_snake_case)]
#[allow(dead_code)]
impl IMS100BatchHandler {
impl Ims100BatchHandler {
pub fn new(
id: UniqueApidTargetId,
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
@ -222,7 +197,6 @@ impl IMS100BatchHandler {
self.stamp_helper.update_from_now();
// Handle requests.
self.handle_composite_requests();
// self.handle_mode_requests();
}
pub fn handle_composite_requests(&mut self) {
@ -264,32 +238,31 @@ impl IMS100BatchHandler {
requestor_info: &MessageMetadata,
action_request: &ActionRequest,
) -> Result<(), CameraError> {
let param =
match CameraActionId::try_from(action_request.action_id).expect("Invalid action id") {
CameraActionId::DefaultSingle => DEFAULT_SINGLE_CAM_PARAMS,
CameraActionId::BalancedSingle => BALANCED_SINGLE_CAM_PARAMS,
CameraActionId::DefaultSingleFlatSat => DEFAULT_SINGLE_FLATSAT_CAM_PARAMS,
CameraActionId::BalancedSingleFlatSat => BALANCED_SINGLE_FLATSAT_CAM_PARAMS,
CameraActionId::CustomParameters => match &action_request.variant {
ActionRequestVariant::NoData => return Err(CameraError::NoDataSent),
ActionRequestVariant::StoreData(_) => {
// let param = serde_json::from_slice()
// TODO implement non dynamic version
return Err(CameraError::VariantNotImplemented);
}
ActionRequestVariant::VecData(data) => {
let param: serde_json::Result<CameraPictureParameters> =
serde_json::from_slice(data.as_slice());
match param {
Ok(param) => param,
Err(_) => {
return Err(CameraError::DeserializeError);
}
let param = match ActionId::try_from(action_request.action_id).expect("Invalid action id") {
ActionId::DefaultSingle => DEFAULT_SINGLE_CAM_PARAMS,
ActionId::BalancedSingle => BALANCED_SINGLE_CAM_PARAMS,
ActionId::DefaultSingleFlatSat => DEFAULT_SINGLE_FLATSAT_CAM_PARAMS,
ActionId::BalancedSingleFlatSat => BALANCED_SINGLE_FLATSAT_CAM_PARAMS,
ActionId::CustomParameters => match &action_request.variant {
ActionRequestVariant::NoData => return Err(CameraError::NoDataSent),
ActionRequestVariant::StoreData(_) => {
// let param = serde_json::from_slice()
// TODO implement non dynamic version
return Err(CameraError::VariantNotImplemented);
}
ActionRequestVariant::VecData(data) => {
let param: serde_json::Result<CameraPictureParameters> =
serde_json::from_slice(data.as_slice());
match param {
Ok(param) => param,
Err(_) => {
return Err(CameraError::DeserializeError);
}
}
_ => return Err(CameraError::VariantNotImplemented),
},
};
}
_ => return Err(CameraError::VariantNotImplemented),
},
};
let output = self.take_picture(param)?;
info!("Sending action reply!");
send_data_reply(self.id, output.stdout, &self.stamp_helper, &self.tm_tx)?;
@ -388,8 +361,7 @@ impl IMS100BatchHandler {
#[cfg(test)]
mod tests {
use crate::handlers::camera::{
CameraActionId, CameraPictureParameters, IMS100BatchHandler,
DEFAULT_SINGLE_FLATSAT_CAM_PARAMS,
ActionId, CameraPictureParameters, Ims100BatchHandler, DEFAULT_SINGLE_FLATSAT_CAM_PARAMS,
};
use crate::requests::CompositeRequest;
use ops_sat_rs::config::components::CAMERA_HANDLER;
@ -399,32 +371,47 @@ mod tests {
use satrs::request::{GenericMessage, MessageMetadata};
use satrs::tmtc::PacketAsVec;
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
fn create_handler() -> (
IMS100BatchHandler,
Sender<GenericMessage<CompositeRequest>>,
Receiver<PacketAsVec>,
Receiver<GenericMessage<ActionReplyPus>>,
) {
let (composite_request_tx, composite_request_rx) = mpsc::channel();
let (tm_tx, tm_rx) = mpsc::channel();
let (action_reply_tx, action_reply_rx) = mpsc::channel();
let time_helper = TimeStampHelper::default();
let cam_handler: IMS100BatchHandler = IMS100BatchHandler::new(
CAMERA_HANDLER,
composite_request_rx,
tm_tx,
action_reply_tx,
time_helper,
);
(cam_handler, composite_request_tx, tm_rx, action_reply_rx)
struct Ims1000Testbench {
pub handler: Ims100BatchHandler,
pub composite_req_tx: mpsc::Sender<GenericMessage<CompositeRequest>>,
pub tm_receiver: mpsc::Receiver<PacketAsVec>,
pub action_reply_rx: mpsc::Receiver<GenericMessage<ActionReplyPus>>,
}
impl Default for Ims1000Testbench {
fn default() -> Self {
let (composite_request_tx, composite_request_rx) = mpsc::channel();
let (tm_tx, tm_rx) = mpsc::channel();
let (action_reply_tx, action_reply_rx) = mpsc::channel();
let time_helper = TimeStampHelper::default();
let cam_handler: Ims100BatchHandler = Ims100BatchHandler::new(
CAMERA_HANDLER,
composite_request_rx,
tm_tx,
action_reply_tx,
time_helper,
);
Ims1000Testbench {
handler: Ims100BatchHandler::new(
CAMERA_HANDLER,
composite_request_rx,
tm_tx,
action_reply_tx,
time_helper,
),
composite_req_tx: composite_request_tx,
tm_receiver: tm_rx,
action_reply_rx,
}
}
}
#[test]
fn command_line_execution() {
let (mut cam_handler, req_tx, tm_rx, action_reply_rx) = create_handler();
cam_handler
let mut testbench = Ims1000Testbench::default();
testbench
.handler
.take_picture(DEFAULT_SINGLE_FLATSAT_CAM_PARAMS)
.unwrap();
}
@ -439,33 +426,34 @@ mod tests {
#[test]
fn test_action_req() {
let (mut cam_handler, req_tx, tm_rx, action_reply_rx) = create_handler();
let mut testbench = Ims1000Testbench::default();
let data = serde_json::to_string(&DEFAULT_SINGLE_FLATSAT_CAM_PARAMS).unwrap();
let req = ActionRequest::new(
CameraActionId::CustomParameters as u32,
ActionId::CustomParameters as u32,
ActionRequestVariant::VecData(data.as_bytes().to_vec()),
);
cam_handler
testbench
.handler
.handle_action_request(&MessageMetadata::new(1, 1), &req)
.unwrap();
}
#[test]
fn test_action_req_channel() {
let (mut cam_handler, req_tx, tm_rx, action_reply_rx) = create_handler();
let mut testbench = Ims1000Testbench::default();
let data = serde_json::to_string(&DEFAULT_SINGLE_FLATSAT_CAM_PARAMS).unwrap();
let req = ActionRequest::new(
CameraActionId::CustomParameters as u32,
ActionId::CustomParameters as u32,
ActionRequestVariant::VecData(data.as_bytes().to_vec()),
);
let req = CompositeRequest::Action(req);
req_tx
testbench
.composite_req_tx
.send(GenericMessage::new(MessageMetadata::new(1, 1), req))
.unwrap();
cam_handler.periodic_operation();
testbench.handler.periodic_operation();
}
}

View File

@ -33,7 +33,7 @@ use crate::{
PusTcDistributor, PusTcMpscRouter,
},
};
use crate::{handlers::camera::IMS100BatchHandler, pus::event::create_event_service};
use crate::{handlers::camera::Ims100BatchHandler, pus::event::create_event_service};
use crate::{
interface::tcp_server::{SyncTcpTmSource, TcpTask},
interface::udp_server::{DynamicUdpTmHandler, UdpTmtcServer},
@ -211,7 +211,7 @@ fn main() {
.expect("creating TCP SPP client failed");
let timestamp_helper = TimeStampHelper::default();
let mut camera_handler: IMS100BatchHandler = IMS100BatchHandler::new(
let mut camera_handler: Ims100BatchHandler = Ims100BatchHandler::new(
CAMERA_HANDLER,
camera_composite_rx,
tm_funnel_tx.clone(),