camera_tests #13

Merged
muellerr merged 9 commits from camera_tests into main 2024-04-24 17:43:41 +02:00
10 changed files with 362 additions and 39 deletions
Showing only changes of commit 028de494e4 - Show all commits

201
Cargo.lock generated
View File

@ -304,6 +304,95 @@ dependencies = [
"log",
]
[[package]]
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.59",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
@ -326,6 +415,20 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "homedir"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22074da8bba2ef26fc1737ae6c777b5baab5524c2dc403b5c6a76166766ccda5"
dependencies = [
"cfg-if",
"nix",
"serde",
"widestring",
"windows-sys 0.48.0",
"wmi",
]
[[package]]
name = "humantime"
version = "2.1.0"
@ -410,6 +513,15 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "mio"
version = "0.8.11"
@ -422,6 +534,19 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "nix"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
dependencies = [
"bitflags",
"cfg-if",
"libc",
"memoffset",
"pin-utils",
]
[[package]]
name = "nodrop"
version = "0.1.14"
@ -482,6 +607,7 @@ dependencies = [
"derive-new",
"env_logger",
"fern",
"homedir",
"humantime",
"lazy_static",
"log",
@ -514,6 +640,18 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro-crate"
version = "3.1.0"
@ -693,6 +831,15 @@ dependencies = [
"serde",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "0.6.14"
@ -893,6 +1040,24 @@ version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "widestring"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core",
"windows-implement",
"windows-interface",
"windows-targets 0.52.5",
]
[[package]]
name = "windows-core"
version = "0.52.0"
@ -902,6 +1067,28 @@ dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-implement"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.59",
]
[[package]]
name = "windows-interface"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.59",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
@ -1050,6 +1237,20 @@ dependencies = [
"memchr",
]
[[package]]
name = "wmi"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f0a4062ca522aad4705a2948fd4061b3857537990202a8ddd5af21607f79a"
dependencies = [
"chrono",
"futures",
"log",
"serde",
"thiserror",
"windows",
]
[[package]]
name = "zerocopy"
version = "0.7.32"

View File

@ -18,6 +18,7 @@ num_enum = "0.7"
serde = "1"
serde_json = "1"
mio = "0.8"
homedir = "0.2"
[dependencies.satrs]
version = "0.2.0-rc.3"

31
pytmtc/camera_params.py Normal file
View File

@ -0,0 +1,31 @@
import struct
from serde import Model, fields
from common import EXPERIMENT_APID, UniqueId, make_addressable_id
class CameraParameters(Model):
R: fields.Int()
G: fields.Int()
B: fields.Int()
N: fields.Int()
P: fields.Bool()
E: fields.Int()
W: fields.Int()
def serialize_for_uplink(self) -> bytearray:
return self.to_json().encode('utf-8')
# Example serialization
data = bytearray(make_addressable_id(EXPERIMENT_APID, UniqueId.CameraHandler))
params = CameraParameters(8, 8, 8, 1, True, 200, 1000)
serialized = params.to_json().encode('utf-8')
byte_string = bytearray(struct.pack('!{}s'.format(len(serialized)), serialized))
print(byte_string)
print(params.serialize_for_uplink())
data.extend(params.serialize_for_uplink())
print(data)
# Example deserialization
data = '{"R": 100, "G": 150, "B": 200, "N": 3, "P": true, "E": 10, "W": 20}'
deserialized_params = CameraParameters.from_json(data)
print(deserialized_params)

View File

@ -3,13 +3,29 @@ from __future__ import annotations
import dataclasses
import enum
import struct
from serde import Model, fields
EXPERIMENT_ID = 278
EXPERIMENT_APID = 1024 + EXPERIMENT_ID
class UniqueId(enum.IntEnum):
Controller = 0
PusEventManagement = 1
PusRouting = 2
PusTest = 3
PusAction = 4
PusMode = 5
PusHk = 6
UdpServer = 7
TcpServer = 8
TcpSppClient = 9
CameraHandler = 10
class EventSeverity(enum.IntEnum):
INFO = 0
LOW = 1
MEDIUM = 2
@ -43,6 +59,12 @@ class AcsHkIds(enum.IntEnum):
def make_addressable_id(target_id: int, unique_id: int) -> bytes:
byte_string = bytearray(struct.pack("!I", target_id))
byte_string.extend(struct.pack("!I", unique_id))
byte_string = bytearray(struct.pack("!I", unique_id))
# byte_string = bytearray(struct.pack("!I", target_id))
# byte_string.extend(struct.pack("!I", unique_id))
return byte_string
def make_addressable_id_with_action_id(unique_id: int, action_id: int) -> bytes:
byte_string = bytearray(struct.pack("!I", unique_id))
byte_string.extend(struct.pack("!I", action_id))
return byte_string

View File

@ -9,6 +9,10 @@ from tmtccmd.pus.tc.s200_fsfw_mode import Mode
from tmtccmd.tmtc import DefaultPusQueueHelper
from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd
from tmtccmd.pus.s200_fsfw_mode import Subservice as ModeSubservice
from serde import Model, fields
from camera_params import CameraParameters
from common import EXPERIMENT_APID, UniqueId, make_addressable_id, make_addressable_id_with_action_id
_LOGGER = logging.getLogger(__name__)
@ -65,6 +69,38 @@ def create_cmd_definition_tree() -> CmdTreeNode:
)
root_node.add_child(scheduler_node)
action_node = CmdTreeNode("action", "Action Node")
cam_node = CmdTreeNode(
"take_image", "Take Image with IMS Imager"
)
cam_node.add_child(
CmdTreeNode(
"default_single", "Default Single Image Camera Parameters"
)
)
cam_node.add_child(
CmdTreeNode(
"balanced_single", "Balanced Single Image Camera Parameters"
)
)
cam_node.add_child(
CmdTreeNode(
"default_single_flatsat", "Default Single Image Camera Parameters for use on FlatSat"
)
)
cam_node.add_child(
CmdTreeNode(
"balanced_single_flatsat", "Balanced Single Image Camera Parameters for use on FlatSat"
)
)
cam_node.add_child(
CmdTreeNode(
"custom_params", "Custom Camera Parameters as specified from file"
)
)
action_node.add_child(cam_node)
root_node.add_child(action_node)
return root_node
@ -97,6 +133,26 @@ def pack_pus_telecommands(q: DefaultPusQueueHelper, cmd_path: str):
)
if cmd_path_list[0] == "acs":
assert len(cmd_path_list) >= 2
if cmd_path_list[0] == "action":
assert len(cmd_path_list)>= 2
if cmd_path_list[1] == "take_image":
assert len(cmd_path_list)>= 3
q.add_log_cmd("Sending PUS take image action request with " + cmd_path_list[2] + " params.")
if cmd_path_list[2] == "default_single":
data = make_addressable_id_with_action_id(UniqueId.CameraHandler, 1)
if cmd_path_list[2] == "balanced_single":
data = make_addressable_id_with_action_id(UniqueId.CameraHandler, 2)
if cmd_path_list[2] == "default_single_flatsat":
data = make_addressable_id_with_action_id(UniqueId.CameraHandler, 3)
if cmd_path_list[2] == "balanced_single_flatsat":
data = make_addressable_id_with_action_id(UniqueId.CameraHandler, 4)
if cmd_path_list[2] == "custom":
data = make_addressable_id_with_action_id(UniqueId.CameraHandler, 5)
params = CameraParameters(8, 8, 8, 1, True, 200, 1000)
bytes = params.serialize_for_uplink()
data.extend(bytes)
print(data.hex(sep=","))
return q.add_pus_tc(PusTelecommand(service=8, subservice=128, apid=EXPERIMENT_APID, app_data=data))
def handle_set_mode_cmd(

View File

@ -35,4 +35,12 @@ def tc_definitions() -> TmtcDefinitionWrapper:
info="PUS Service 11 TC Scheduling",
op_code_entry=srv_11,
)
srv_8 = OpCodeEntry()
srv_8.add("pic", "Action Request Image")
defs.add_service(
name=CoreServiceList.SERVICE_8,
info="PUS Service 8 Action",
op_code_entry=srv_8,
)
return defs

BIN
scripts/ims100_testapp Normal file

Binary file not shown.

View File

@ -8,7 +8,7 @@ use std::net::Ipv4Addr;
use std::path::{Path, PathBuf};
pub const STOP_FILE_NAME: &str = "stop-experiment";
pub const HOME_FOLER_EXPERIMENT: &str = "/home/exp278";
pub const HOME_FOLDER_EXPERIMENT: &str = "/home/exp278";
pub const LOG_FOLDER: &str = "logs";
pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
@ -40,12 +40,13 @@ pub enum GroupId {
lazy_static! {
pub static ref HOME_PATH: PathBuf = {
let home_path_default = env::var("HOME").expect("HOME env variable not set");
let mut home_path = PathBuf::new();
home_path.push(if Path::new(HOME_FOLER_EXPERIMENT).exists() {
HOME_FOLER_EXPERIMENT
let mut home_path_default = homedir::get_my_home().expect("Getting home dir from OS failed.").expect("No home dir found.");
home_path.push(if Path::new(HOME_FOLDER_EXPERIMENT).exists() {
HOME_FOLDER_EXPERIMENT
} else {
&home_path_default
home_path_default.to_str().expect("Error converting to string.")
});
home_path
};

View File

@ -36,7 +36,9 @@ use serde::{Deserialize, Serialize};
use std::io::Error;
use std::process::Command;
use std::sync::mpsc;
use satrs::pus::action::ActionReplyPus;
use satrs::pus::action::{ActionReplyPus, ActionReplyVariant};
const IMS_TESTAPP: &str = "scripts/ims100_testapp";
const DEFAULT_SINGLE_CAM_PARAMS: CameraPictureParameters = CameraPictureParameters {
R: 8,
@ -83,7 +85,7 @@ const BALANCED_SINGLE_FLATSAT_CAM_PARAMS: CameraPictureParameters = CameraPictur
// TODO howto downlink
#[derive(Debug)]
pub enum CameraActionIds {
pub enum CameraActionId {
DefaultSingle = 1,
BalancedSingle = 2,
DefaultSingleFlatSat = 3,
@ -91,25 +93,25 @@ pub enum CameraActionIds {
CustomParameters = 5,
}
impl TryFrom<u32> for CameraActionIds {
impl TryFrom<u32> for CameraActionId {
type Error = ();
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
value if value == CameraActionIds::DefaultSingle as u32 => {
Ok(CameraActionIds::DefaultSingle)
value if value == CameraActionId::DefaultSingle as u32 => {
Ok(CameraActionId::DefaultSingle)
}
value if value == CameraActionIds::BalancedSingle as u32 => {
Ok(CameraActionIds::BalancedSingle)
value if value == CameraActionId::BalancedSingle as u32 => {
Ok(CameraActionId::BalancedSingle)
}
value if value == CameraActionIds::DefaultSingleFlatSat as u32 => {
Ok(CameraActionIds::DefaultSingleFlatSat)
value if value == CameraActionId::DefaultSingleFlatSat as u32 => {
Ok(CameraActionId::DefaultSingleFlatSat)
}
value if value == CameraActionIds::BalancedSingleFlatSat as u32 => {
Ok(CameraActionIds::BalancedSingleFlatSat)
value if value == CameraActionId::BalancedSingleFlatSat as u32 => {
Ok(CameraActionId::BalancedSingleFlatSat)
}
value if value == CameraActionIds::CustomParameters as u32 => {
Ok(CameraActionIds::CustomParameters)
value if value == CameraActionId::CustomParameters as u32 => {
Ok(CameraActionId::CustomParameters)
}
_ => Err(()),
}
@ -193,15 +195,15 @@ impl IMS100BatchHandler {
pub fn handle_action_request(
&mut self,
_requestor_info: &MessageMetadata,
requestor_info: &MessageMetadata,
action_request: &ActionRequest,
) -> std::io::Result<()> {
let param = match CameraActionIds::try_from(action_request.action_id).unwrap() {
CameraActionIds::DefaultSingle => DEFAULT_SINGLE_CAM_PARAMS,
CameraActionIds::BalancedSingle => BALANCED_SINGLE_CAM_PARAMS,
CameraActionIds::DefaultSingleFlatSat => DEFAULT_SINGLE_FLATSAT_CAM_PARAMS,
CameraActionIds::BalancedSingleFlatSat => BALANCED_SINGLE_FLATSAT_CAM_PARAMS,
CameraActionIds::CustomParameters => match &action_request.variant {
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(Error::other("No Data sent!")),
ActionRequestVariant::StoreData(_) => {
// let param = serde_json::from_slice()
@ -223,11 +225,13 @@ impl IMS100BatchHandler {
_ => return Err(Error::other("Invalid Action Request Variant!")),
},
};
self.take_picture(param)
self.take_picture(param)?;
self.action_reply_tx.send(GenericMessage::new(*requestor_info, ActionReplyPus::new(action_request.action_id, ActionReplyVariant::Completed))).unwrap();
Ok(())
}
pub fn take_picture(&mut self, param: CameraPictureParameters) -> std::io::Result<()> {
let mut cmd = Command::new("ims100_testapp");
let mut cmd = Command::new(IMS_TESTAPP);
cmd.arg("-R")
.arg(&param.R.to_string())
.arg("-G")
@ -314,7 +318,7 @@ impl IMS100BatchHandler {
#[cfg(test)]
mod tests {
use crate::handlers::camera::{
CameraActionIds, CameraPictureParameters, IMS100BatchHandler,
CameraActionId, CameraPictureParameters, IMS100BatchHandler,
DEFAULT_SINGLE_FLATSAT_CAM_PARAMS,
};
use crate::requests::CompositeRequest;
@ -359,7 +363,7 @@ mod tests {
let data = serde_json::to_string(&DEFAULT_SINGLE_FLATSAT_CAM_PARAMS).unwrap();
let req = ActionRequest::new(
CameraActionIds::CustomParameters as u32,
CameraActionId::CustomParameters as u32,
ActionRequestVariant::VecData(data.as_bytes().to_vec()),
);
@ -374,7 +378,7 @@ mod tests {
let data = serde_json::to_string(&DEFAULT_SINGLE_FLATSAT_CAM_PARAMS).unwrap();
let req = ActionRequest::new(
CameraActionIds::CustomParameters as u32,
CameraActionId::CustomParameters as u32,
ActionRequestVariant::VecData(data.as_bytes().to_vec()),
);
let req = CompositeRequest::Action(req);

View File

@ -1,4 +1,4 @@
use std::path::Path;
use std::path::{Path, PathBuf};
use ops_sat_rs::config::LOG_FOLDER;
@ -6,6 +6,9 @@ pub fn setup_logger() -> Result<(), fern::InitError> {
if !Path::new(LOG_FOLDER).exists() && std::fs::create_dir_all(LOG_FOLDER).is_err() {
eprintln!("Failed to create log folder '{}'", LOG_FOLDER);
}
let mut path_buf = PathBuf::from(LOG_FOLDER);
path_buf.push(format!("output.log"));
println!("{:?}", path_buf);
fern::Dispatch::new()
.format(move |out, message, record| {
out.finish(format_args!(
@ -18,11 +21,7 @@ pub fn setup_logger() -> Result<(), fern::InitError> {
})
.level(log::LevelFilter::Debug)
.chain(std::io::stdout())
.chain(fern::log_file(format!(
"{}/output_{}.log",
LOG_FOLDER,
humantime::format_rfc3339_seconds(std::time::SystemTime::now())
))?)
.chain(fern::log_file(path_buf.as_os_str())?)
.apply()?;
Ok(())
}