9 Commits

16 changed files with 977 additions and 425 deletions

View File

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cross Remote Debug" type="com.jetbrains.cidr.remote.gdbserver.type" factoryName="com.jetbrains.cidr.remote.gdbserver.factory" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="eurosim-obsw" TARGET_NAME="Cross" CONFIG_NAME="Cross" version="1" RUN_PATH="$PROJECT_DIR$/target/armv7-unknown-linux-gnueabihf/debug/eurosim-obsw"> <configuration default="false" name="Cross Remote Debug" type="com.jetbrains.cidr.remote.gdbserver.type" factoryName="com.jetbrains.cidr.remote.gdbserver.factory" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="eurosim-obsw" TARGET_NAME="Cross" CONFIG_NAME="Cross" version="1" RUN_PATH="$PROJECT_DIR$/target/armv7-unknown-linux-gnueabihf/debug/eurosim-obsw">
<custom-gdb-server version="1" gdb-connect="obc.local:1234" executable="" warmup-ms="0" download-type="ALWAYS" sshConfigName="koesterl@obc.local:22 password" uploadFile="/tmp/CLion/debug/eurosim-obsw" defaultGdbServerArgs=":1234 /tmp/CLion/debug/eurosim-obsw"> <custom-gdb-server version="1" gdb-connect="192.168.1.116:1234" executable="" warmup-ms="0" download-type="ALWAYS" sshConfigName="koesterl@192.168.1.116:22 password" uploadFile="/tmp/CLion/debug/eurosim-obsw" defaultGdbServerArgs=":1234 /tmp/CLion/debug/eurosim-obsw">
<debugger kind="GDB" isBundled="true" /> <debugger kind="GDB" isBundled="true" />
</custom-gdb-server> </custom-gdb-server>
<method v="2"> <method v="2">

5
Cargo.lock generated
View File

@ -288,6 +288,7 @@ dependencies = [
name = "eurosim-obsw" name = "eurosim-obsw"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"byteorder",
"chrono", "chrono",
"embedded-can", "embedded-can",
"fern", "fern",
@ -812,9 +813,9 @@ dependencies = [
[[package]] [[package]]
name = "spacepackets" name = "spacepackets"
version = "0.5.3" version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81541fd89a5bc02845a849895d6ed1721235b3eac26fc77010f0a05f53bc4e8a" checksum = "9313bf066de3ae704ea83584fc65b62434249efe57ae2dcde3e2cffe4ba62648"
dependencies = [ dependencies = [
"chrono", "chrono",
"crc", "crc",

View File

@ -26,6 +26,8 @@ strum_macros = "0.24"
num = "0.4" num = "0.4"
num-derive = "0.3" num-derive = "0.3"
num-traits = "0.2" num-traits = "0.2"
byteorder = "1.4"
[dependencies.socketcan] [dependencies.socketcan]
git = "https://github.com/socketcan-rs/socketcan-rs.git" git = "https://github.com/socketcan-rs/socketcan-rs.git"

43
output.log Normal file
View File

@ -0,0 +1,43 @@
[2023-02-15][09:14:42][main][INFO] Starting TMTC task
[2023-02-15][09:14:42][main][INFO] Starting power task
[2023-02-15][09:14:42][main][INFO] Starting AOCS task
[2023-02-15][09:16:43][main][INFO] Starting TMTC task
[2023-02-15][09:16:43][main][INFO] Starting power task
[2023-02-15][09:16:43][main][INFO] Starting AOCS task
[2023-02-15][11:05:33][main][INFO] Starting TMTC task
[2023-02-15][11:05:33][main][INFO] Starting CAN Socket listening task
[2023-02-15][11:05:33][main][INFO] Starting CAN Socket writing task
[2023-02-15][11:05:33][main][INFO] Starting power task
[2023-02-15][11:05:33][main][INFO] Starting AOCS task
[2023-02-15][11:10:52][main][INFO] Starting TMTC task
[2023-02-15][11:10:52][main][INFO] Starting power task
[2023-02-15][11:10:52][main][INFO] Starting AOCS task
[2023-02-15][11:11:09][main][INFO] Starting TMTC task
[2023-02-15][11:11:09][main][INFO] Starting power task
[2023-02-15][11:11:09][main][INFO] Starting AOCS task
[2023-02-15][11:11:37][main][INFO] Starting TMTC task
[2023-02-15][11:11:37][main][INFO] Starting power task
[2023-02-15][11:11:37][main][INFO] Starting AOCS task
[2023-02-15][14:42:44][main][INFO] Starting TMTC task
[2023-02-15][14:42:44][main][INFO] Starting power task
[2023-02-15][14:42:44][main][INFO] Starting Payload Handling task
[2023-02-15][14:42:44][main][INFO] Starting TM funnel task
[2023-02-15][14:42:44][main][INFO] Starting AOCS task
[2023-02-15][14:43:13][main][INFO] Running DemoSat OBSW
[2023-02-15][14:43:13][main][INFO] Starting TMTC task
[2023-02-15][14:43:13][main][INFO] Starting power task
[2023-02-15][14:43:13][main][INFO] Starting Payload Handling task
[2023-02-15][14:43:13][main][INFO] Starting TM funnel task
[2023-02-15][14:43:13][main][INFO] Starting AOCS task
[2023-02-15][14:48:12][main][INFO] Running DemoSat OBSW!
[2023-02-15][14:48:12][main][INFO] Starting TMTC task
[2023-02-15][14:48:12][main][INFO] Starting power task
[2023-02-15][14:48:12][main][INFO] Starting Payload Handling task
[2023-02-15][14:48:12][main][INFO] Starting TM funnel task
[2023-02-15][14:48:12][main][INFO] Starting AOCS task
[2023-02-16][12:46:02][main][INFO] Running DemoSat OBSW!
[2023-02-16][12:46:02][main][INFO] Starting TMTC task
[2023-02-16][12:46:02][main][INFO] Starting power task
[2023-02-16][12:46:02][main][INFO] Starting Payload Handling task
[2023-02-16][12:46:02][main][INFO] Starting TM funnel task
[2023-02-16][12:46:02][main][INFO] Starting AOCS task

View File

@ -7,6 +7,8 @@ import sys
import time import time
from typing import Optional from typing import Optional
import datetime import datetime
import json
import pprint
import tmtccmd import tmtccmd
from spacepackets.ecss import PusTelemetry, PusTelecommand, PusVerificator from spacepackets.ecss import PusTelemetry, PusTelecommand, PusVerificator
@ -110,6 +112,7 @@ class SatRsConfigHook(HookBase):
srv_11 = OpCodeEntry() srv_11 = OpCodeEntry()
srv_11.add("0", "Scheduled TC Test") srv_11.add("0", "Scheduled TC Test")
srv_11.add("1", "Scheduled Camera Request TC")
defs.add_service( defs.add_service(
name=CoreServiceList.SERVICE_11, name=CoreServiceList.SERVICE_11,
info="PUS Service 11 TC Scheduling", info="PUS Service 11 TC Scheduling",
@ -168,13 +171,15 @@ class PusHandler(SpecificApidHandlerBase):
self.verif_wrapper.log_to_file(tm_packet, res) self.verif_wrapper.log_to_file(tm_packet, res)
dedicated_handler = True dedicated_handler = True
if service == 3: if service == 3:
_LOGGER.info("No handling for HK packets implemented") # _LOGGER.info("No handling for HK packets implemented")
_LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]") # _LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]")
pus_tm = PusTelemetry.unpack(packet, time_reader=CdsShortTimestamp.empty()) pus_tm = PusTelemetry.unpack(packet, time_reader=CdsShortTimestamp.empty())
if pus_tm.subservice == 25: if pus_tm.subservice == 25:
if len(pus_tm.source_data) < 8: if len(pus_tm.source_data) < 8:
raise ValueError("No addressable ID in HK packet") raise ValueError("No addressable ID in HK packet")
json_str = pus_tm.source_data[8:] json_str = str(pus_tm.source_data[8:].decode('utf8'))
json_object = json.loads(json_str)
pprint.pprint(json_object)
dedicated_handler = True dedicated_handler = True
if service == 5: if service == 5:
tm_packet = Service5Tm.unpack(packet, time_reader=CdsShortTimestamp.empty()) tm_packet = Service5Tm.unpack(packet, time_reader=CdsShortTimestamp.empty())
@ -218,6 +223,9 @@ def read_addressable_id(data: bytes) -> tuple[int, int]:
return (target_id, set_id) return (target_id, set_id)
class CustomServiceList(enum.IntEnum):
ACS = "acs"
class RequestTargetId(enum.IntEnum): class RequestTargetId(enum.IntEnum):
ACS = 1 ACS = 1
PLD = 2 PLD = 2
@ -286,7 +294,12 @@ class TcHandler(TcHandlerBase):
): ):
q.add_log_cmd("Sending PUS ping telecommand") q.add_log_cmd("Sending PUS ping telecommand")
return q.add_pus_tc(PusTelecommand(service=17, subservice=1)) return q.add_pus_tc(PusTelecommand(service=17, subservice=1))
if service == CustomServiceList.ACS:
if op_code == "set_mode":
q.add_log_cmd()
q.add_pus_tc()
if service == CoreServiceList.SERVICE_11: if service == CoreServiceList.SERVICE_11:
if op_code == "0":
q.add_log_cmd("Sending PUS scheduled TC telecommand") q.add_log_cmd("Sending PUS scheduled TC telecommand")
crt_time = CdsShortTimestamp.from_now() crt_time = CdsShortTimestamp.from_now()
time_stamp = crt_time + datetime.timedelta(seconds=10) time_stamp = crt_time + datetime.timedelta(seconds=10)
@ -298,6 +311,18 @@ class TcHandler(TcHandlerBase):
apid=EXAMPLE_PUS_APID, apid=EXAMPLE_PUS_APID,
) )
) )
if op_code == "1":
q.add_log_cmd("Sending PUS scheduled TC telecommand")
crt_time = CdsShortTimestamp.from_now()
time_stamp = crt_time + datetime.timedelta(seconds=10)
time_stamp = time_stamp.pack()
return q.add_pus_tc(
create_time_tagged_cmd(
time_stamp,
PusTelecommand(service=8, subservice=1, app_data=make_target_id(RequestTargetId.PLD)),
apid=EXAMPLE_PUS_APID,
)
)
if service == CoreServiceList.SERVICE_8: if service == CoreServiceList.SERVICE_8:
q.add_log_cmd("Sending PUS action request telecommand") q.add_log_cmd("Sending PUS action request telecommand")
return q.add_pus_tc( return q.add_pus_tc(

View File

@ -1,6 +1,7 @@
{ {
"com_if": "udp", "com_if": "udp",
"tcpip_udp_ip_addr": "169.254.7.6", "tcpip_udp_ip_addr": "192.168.1.116",
"tcpip_udp_ip_addr_windows": "192.168.1.5",
"tcpip_udp_port": 7301, "tcpip_udp_port": 7301,
"tcpip_udp_recv_max_size": 1500 "tcpip_udp_recv_max_size": 1500
} }

206
src/aocs_handler.rs Normal file
View File

@ -0,0 +1,206 @@
use std::sync::{Arc, Mutex};
use crate::can_ids::{DeviceId, PackageId, PackageModel};
use crate::hk::HkRequest;
use crate::power_handler::{DeviceState, PowerSwitcher};
use crate::requests::{Request, RequestWithToken};
use satrs_core::power::SwitchId;
use std::sync::mpsc::{Receiver, Sender};
use serde::{Deserialize, Serialize};
use byteorder::{LittleEndian, ByteOrder};
use crate::can_ids::PackageId::AOCSDataRequestMGM1;
pub enum AocsSensorMode {
Idle,
SendingData,
}
pub trait AocsSensorHandler {
type Error;
fn get_package_id(&mut self) -> Result<PackageId, Self::Error>;
fn send_message(&mut self, id: PackageId, buf: &[u8]) -> Result<(), Self::Error>;
fn enable_sensor_data_generation(&mut self) -> Result<(), Self::Error> {
let id = self.get_package_id()?;
self.send_message(id, &[1])
}
fn disable_sensor_data_generation(&mut self) -> Result<(), Self::Error> {
let id = self.get_package_id()?;
self.send_message(id, &[0])
}
fn request_sensor_data_oneshot(&mut self) -> Result<(), Self::Error> {
let id = self.get_package_id()?;
self.send_message(id, &[2])
}
}
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct MGMData {
axis_1: f64,
axis_2: f64,
axis_3: f64,
}
impl MGMData {
pub fn from_floats(axis_1: f64,
axis_2: f64,
axis_3: f64,
) -> MGMData {
MGMData{axis_1, axis_2, axis_3}
}
pub fn new() -> MGMData { MGMData{axis_1: 0.0, axis_2: 0.0, axis_3: 0.0} }
pub fn update(&mut self,
axis_1: f64,
axis_2: f64,
axis_3: f64
) {
self.axis_1 = axis_1;
self.axis_2 = axis_2;
self.axis_3 = axis_3;
}
pub fn to_array(&self) -> [f64; 3] {
[self.axis_1, self.axis_2, self.axis_3]
}
pub fn to_tuple(&self) -> (f64, f64, f64) {
(self.axis_1, self.axis_2, self.axis_3)
}
}
pub struct MGMHandler {
power_switcher: PowerSwitcher,
device_id: DeviceId,
switch_id: SwitchId,
device_state: DeviceState,
can_tx: Sender<PackageModel>,
can_rx: Receiver<PackageModel>,
mode: AocsSensorMode,
mode_rx: Receiver<AocsSensorMode>,
action_rx: Receiver<RequestWithToken>,
mgm_data: Arc<Mutex<MGMData>>,
sensor_data_enabled: bool,
}
impl AocsSensorHandler for MGMHandler {
type Error = ();
fn get_package_id(&mut self) -> Result<PackageId, Self::Error> {
return match self.device_id {
DeviceId::MGM1 => Ok(PackageId::AOCSDataRequestMGM1),
DeviceId::MGM2 => Ok(PackageId::AOCSDataRequestMGM2),
DeviceId::MGM3 => Ok(PackageId::AOCSDataRequestMGM3),
DeviceId::MGM4 => Ok(PackageId::AOCSDataRequestMGM4),
_ => Err(()),
};
}
fn send_message(&mut self, id: PackageId, buf: &[u8]) -> Result<(), Self::Error> {
self.can_tx.send(PackageModel::new(id, buf).unwrap()).unwrap();
return Ok(());
}
}
impl MGMHandler {
pub fn new(
power_switcher: PowerSwitcher,
device_id: DeviceId,
can_tx: Sender<PackageModel>,
can_rx: Receiver<PackageModel>,
mode_rx: Receiver<AocsSensorMode>,
action_rx: Receiver<RequestWithToken>,
) -> MGMHandler {
let switch_id = device_id as u16;
MGMHandler {
power_switcher,
device_id,
switch_id,
device_state: DeviceState::Off,
can_tx,
can_rx,
mode: AocsSensorMode::Idle,
mode_rx,
action_rx,
mgm_data: Arc::new(Mutex::new(MGMData::new())),
sensor_data_enabled: false,
}
}
pub fn get_data_ref(&mut self) -> Arc<Mutex<MGMData>> {
self.mgm_data.clone()
}
pub fn periodic_op(&mut self) {
self.update_mode();
self.handle_requests();
self.read_sensor_data();
}
pub fn update_mode(&mut self) {
if self.device_state == DeviceState::On {
if let Ok(mode) = self.mode_rx.try_recv() {
self.mode = mode;
}
}
}
pub fn handle_requests(&mut self) {
if self.device_state == DeviceState::On {
if let Ok(request) = self.action_rx.try_recv() {
match request.0 {
Request::HkRequest(hk_req) => {
self.handle_hk_request(hk_req);
}
Request::ActionRequest(_action_request) => {
//self.handle_action_request(action_request);
}
}
}
}
}
pub fn handle_hk_request(&mut self, hk_req: HkRequest) {
match hk_req {
HkRequest::OneShot(_) => {
self.can_tx.send(PackageModel::new(PackageId::AOCSDataRequestMGM1, &[2]).unwrap()).unwrap();
}
HkRequest::Enable(_) => {
if !self.sensor_data_enabled {
self.sensor_data_enabled = true;
self.can_tx.send(PackageModel::new(PackageId::AOCSDataRequestMGM1, &[1]).unwrap()).unwrap();
}
}
HkRequest::Disable(_) => {
if self.sensor_data_enabled {
self.sensor_data_enabled = false;
self.can_tx.send(PackageModel::new(PackageId::AOCSDataRequestMGM1, &[0]).unwrap()).unwrap();
}
}
HkRequest::ModifyCollectionInterval(_, _) => {}
}
}
pub fn read_sensor_data(&mut self) {
if let Ok(package) = self.can_rx.try_recv() {
let float_data = self.decode_sensor_data(package.data());
if let Ok(mut mgm_data) = self.mgm_data.lock() {
match package.package_id() {
PackageId::AOCSDataMGM1 => { mgm_data.axis_1 = float_data }
PackageId::AOCSDataMGM2 => { mgm_data.axis_2 = float_data }
PackageId::AOCSDataMGM3 => { mgm_data.axis_3 = float_data }
_ => {}
}
}
}
}
pub fn decode_sensor_data(&mut self, buf: &[u8]) -> f64 {
LittleEndian::read_f64(&buf)
}
//pub fn handle_action_request(&mut self, action_request: ActionRequest) {}
}

View File

@ -1,23 +1,13 @@
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_imports)]
use crate::pcdu::DeviceState;
use crate::can_ids::{ use crate::can_ids::{
can_id_to_package_id, package_id_to_can_id, value_to_package_id, DeviceId, PackageId, can_id_to_package_id, package_id_to_can_id, DeviceId, PackageId,
PackageModel, SenderReceiverThread, ThreadId, PackageModel, SenderReceiverThread, ThreadId,
}; };
use embedded_can::{self, Frame}; use embedded_can::{self, Frame};
use log::{debug, error, info, trace, warn}; use log::{debug, warn};
use serde::{Deserialize, Serialize};
use serde_json;
use socketcan::{errors, frame, socket, CanFrame, Socket}; use socketcan::{errors, frame, socket, CanFrame, Socket};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::c_void;
use std::io; use std::io;
use std::mem::size_of; use std::sync::mpsc::{Receiver, Sender};
use std::sync::mpsc::Sender;
pub struct CanRxHandler { pub struct CanRxHandler {
interface: &'static str, interface: &'static str,
@ -49,21 +39,11 @@ impl CanRxHandler {
} }
} }
/* pub fn process_incoming(&mut self) {
pub fn new_socket_with_filter( if let Some(frame) = self.rx_socket() {
interface: &'static str, self.forward_frame(frame);
can_id_to_sender_id: HashMap<embedded_can::Id, u32>,
can_senders: HashMap<u32, Sender<Vec<u8>>>,
can_filters: &[socket::CanFilter],
) -> Result<CanRxHandler, ()> {
let can_wrapper = Self::new_socket(interface, can_id_to_sender_id, can_senders)?;
let filter_result = can_wrapper.socket.set_filters(can_filters);
if let Err(e) = filter_result {
warn!("Can Bus set filter error: {}", e);
} }
Ok(can_wrapper)
} }
*/
pub fn read_frame(&self) -> io::Result<frame::CanFrame> { pub fn read_frame(&self) -> io::Result<frame::CanFrame> {
let frame = self.socket.read_frame(); let frame = self.socket.read_frame();
@ -75,20 +55,13 @@ impl CanRxHandler {
pub fn rx_socket(&self) -> Option<CanFrame> { pub fn rx_socket(&self) -> Option<CanFrame> {
let frame = self.socket.read_frame().ok()?; let frame = self.socket.read_frame().ok()?;
info!("Can Frame read: {:?}.", frame); debug!("Can Frame read: {:?}.", frame);
return Some(frame); return Some(frame);
/*
if let Ok(frame) = frame {
println!("Frame received: {:?}", frame);
return Some(frame);
}
None
*/
} }
pub fn forward_frame(&self, frame: CanFrame) { pub fn forward_frame(&self, frame: CanFrame) {
let frame_id = can_id_to_package_id(frame.id()); let frame_id = can_id_to_package_id(frame.id());
info!("Frame forwarding with id: {:?}", frame_id); debug!("Frame forwarding with id: {:?}", frame_id);
if let Some(frame_id) = frame_id { if let Some(frame_id) = frame_id {
if self.package_map.contains_key(&frame_id) { if self.package_map.contains_key(&frame_id) {
let value = self.package_map.get(&frame_id).unwrap(); let value = self.package_map.get(&frame_id).unwrap();
@ -106,20 +79,73 @@ impl CanRxHandler {
} }
} }
} }
/*
pub fn set_filter(&self, filters: &[socket::CanFilter]) -> io::Result<()> {
info!("Setting filter with filter {:?}", filters);
let result = self.socket.set_filters(filters);
if let Err(e) = result {
warn!("Can bus socket filter set error: {}", e);
}
Ok(())
}
*/
} }
pub struct CanTxHandler { pub struct CanTxHandler {
interface: &'static str,
socket: socket::CanSocket,
package_map: HashMap<PackageId, SenderReceiverThread>,
message_receiver: Receiver<PackageModel>,
}
impl CanTxHandler {
pub fn new_socket(
interface: &'static str,
package_map: HashMap<PackageId, SenderReceiverThread>,
message_receiver: Receiver<PackageModel>,
) -> Result<CanTxHandler, ()> {
let socket = socket::CanSocket::open(&interface);
if let Ok(socket) = socket {
socket.filter_drop_all().unwrap(); // tx nodes cannot receive data
Ok(CanTxHandler {
interface,
socket,
package_map,
message_receiver,
})
} else {
Err(())
}
}
pub fn process_incoming(&mut self) {
if let Ok(package) = self.message_receiver.recv() {
self.tx_socket(package.package_id(), package.data());
}
}
pub fn tx_socket(&self, package_id: PackageId, data: &[u8]) {
if self.package_map.contains_key(&package_id) {
let value = self.package_map.get(&package_id).unwrap();
if value.get_sender() == DeviceId::OBC {
if data.len() <= 8 {
let frame_id = package_id_to_can_id(&package_id);
let frame = CanFrame::new(frame_id, data);
if let Some(frame) = frame {
self.socket
.write_frame(&frame)
.expect("Error writing frame.");
}
} else {
warn!(
"Message dismissed, data length ({:?}) exceeds 8 bytes",
data.len()
);
}
} else {
warn!(
"Message dismissed, wrong sender id: {:?}",
value.get_sender()
);
}
} else {
warn!("Message dismissed, wrong package id: {:?}", package_id);
}
}
}
/*pub struct CanTxHandler {
interface: &'static str, interface: &'static str,
socket: socket::CanSocket, socket: socket::CanSocket,
thread_id: ThreadId, thread_id: ThreadId,
@ -213,6 +239,8 @@ impl CanTxHandler {
*/ */
} }
*/
pub fn open_socket(interface: &str) -> Result<socket::CanSocket, errors::CanSocketOpenError> { pub fn open_socket(interface: &str) -> Result<socket::CanSocket, errors::CanSocketOpenError> {
let socket = socket::CanSocket::open(&interface); let socket = socket::CanSocket::open(&interface);
return socket; return socket;

View File

@ -95,29 +95,29 @@ impl TryFrom<u16> for DeviceId {
fn try_from(v: u16) -> Result<Self, Self::Error> { fn try_from(v: u16) -> Result<Self, Self::Error> {
match v { match v {
x if x==DeviceId::OBC as u16 => Ok(DeviceId::OBC), x if x == DeviceId::OBC as u16 => Ok(DeviceId::OBC),
x if x==DeviceId::PCDU as u16 => Ok(DeviceId::PCDU), x if x == DeviceId::PCDU as u16 => Ok(DeviceId::PCDU),
x if x==DeviceId::MGM1 as u16 => Ok(DeviceId::MGM1), x if x == DeviceId::MGM1 as u16 => Ok(DeviceId::MGM1),
x if x==DeviceId::MGM2 as u16 => Ok(DeviceId::MGM2), x if x == DeviceId::MGM2 as u16 => Ok(DeviceId::MGM2),
x if x==DeviceId::MGM3 as u16 => Ok(DeviceId::MGM3), x if x == DeviceId::MGM3 as u16 => Ok(DeviceId::MGM3),
x if x==DeviceId::MGM4 as u16 => Ok(DeviceId::MGM4), x if x == DeviceId::MGM4 as u16 => Ok(DeviceId::MGM4),
x if x==DeviceId::SunSensor1 as u16 => Ok(DeviceId::SunSensor1), x if x == DeviceId::SunSensor1 as u16 => Ok(DeviceId::SunSensor1),
x if x==DeviceId::SunSensor2 as u16 => Ok(DeviceId::SunSensor2), x if x == DeviceId::SunSensor2 as u16 => Ok(DeviceId::SunSensor2),
x if x==DeviceId::SunSensor3 as u16 => Ok(DeviceId::SunSensor3), x if x == DeviceId::SunSensor3 as u16 => Ok(DeviceId::SunSensor3),
x if x==DeviceId::SunSensor4 as u16 => Ok(DeviceId::SunSensor4), x if x == DeviceId::SunSensor4 as u16 => Ok(DeviceId::SunSensor4),
x if x==DeviceId::SunSensor5 as u16 => Ok(DeviceId::SunSensor5), x if x == DeviceId::SunSensor5 as u16 => Ok(DeviceId::SunSensor5),
x if x==DeviceId::SunSensor6 as u16 => Ok(DeviceId::SunSensor6), x if x == DeviceId::SunSensor6 as u16 => Ok(DeviceId::SunSensor6),
x if x==DeviceId::StarTracker as u16 => Ok(DeviceId::StarTracker), x if x == DeviceId::StarTracker as u16 => Ok(DeviceId::StarTracker),
x if x==DeviceId::MGT1 as u16 => Ok(DeviceId::MGT1), x if x == DeviceId::MGT1 as u16 => Ok(DeviceId::MGT1),
x if x==DeviceId::MGT2 as u16 => Ok(DeviceId::MGT2), x if x == DeviceId::MGT2 as u16 => Ok(DeviceId::MGT2),
x if x==DeviceId::MGT3 as u16 => Ok(DeviceId::MGT3), x if x == DeviceId::MGT3 as u16 => Ok(DeviceId::MGT3),
x if x==DeviceId::MGT4 as u16 => Ok(DeviceId::MGT4), x if x == DeviceId::MGT4 as u16 => Ok(DeviceId::MGT4),
x if x==DeviceId::RWL1 as u16 => Ok(DeviceId::RWL1), x if x == DeviceId::RWL1 as u16 => Ok(DeviceId::RWL1),
x if x==DeviceId::RWL2 as u16 => Ok(DeviceId::RWL2), x if x == DeviceId::RWL2 as u16 => Ok(DeviceId::RWL2),
x if x==DeviceId::RWL3 as u16 => Ok(DeviceId::RWL3), x if x == DeviceId::RWL3 as u16 => Ok(DeviceId::RWL3),
x if x==DeviceId::RWL4 as u16 => Ok(DeviceId::RWL4), x if x == DeviceId::RWL4 as u16 => Ok(DeviceId::RWL4),
x if x==DeviceId::Camera as u16 => Ok(DeviceId::Camera), x if x == DeviceId::Camera as u16 => Ok(DeviceId::Camera),
x if x==DeviceId::All as u16 => Ok(DeviceId::All), x if x == DeviceId::All as u16 => Ok(DeviceId::All),
_ => Err(()), _ => Err(()),
} }
} }

View File

@ -1,3 +1,4 @@
use log::warn;
use crate::tmtc::{MpscStoreAndSendError, PusTcSource, PUS_APID}; use crate::tmtc::{MpscStoreAndSendError, PusTcSource, PUS_APID};
use satrs_core::spacepackets::{CcsdsPacket, SpHeader}; use satrs_core::spacepackets::{CcsdsPacket, SpHeader};
use satrs_core::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc}; use satrs_core::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc};
@ -29,7 +30,7 @@ impl CcsdsPacketHandler for CcsdsReceiver {
sp_header: &SpHeader, sp_header: &SpHeader,
_tc_raw: &[u8], _tc_raw: &[u8],
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
println!("Unknown APID 0x{:x?} detected", sp_header.apid()); warn!("Unknown APID 0x{:x?} detected", sp_header.apid());
Ok(()) Ok(())
} }
} }

175
src/hk.rs
View File

@ -1,10 +1,30 @@
use crate::aocs_handler::{MGMData};
use crate::requests::Request;
use crate::requests::RequestWithToken;
use crate::tmtc::TmStore;
use eurosim_obsw::{hk_err};
use satrs_core::pool::StoreAddr;
use satrs_core::pus::hk::Subservice;
use satrs_core::pus::verification::{
FailParams, StdVerifSenderError, VerificationReporterWithSender,
};
use satrs_core::seq_count::{SeqCountProviderSyncClonable, SequenceCountProviderCore};
use satrs_core::spacepackets::time::cds::TimeProvider;
use satrs_core::spacepackets::time::TimeWriter;
use satrs_core::spacepackets::tm::{PusTm, PusTmSecondaryHeader};
use satrs_core::spacepackets::SpHeader;
use satrs_core::tmtc::AddressableId; use satrs_core::tmtc::AddressableId;
use serde::{Deserialize, Serialize};
use std::ops::{Deref};
use std::sync::mpsc::{Receiver, Sender};
use std::sync::{Arc, Mutex};
pub type CollectionIntervalFactor = u32; pub type CollectionIntervalFactor = u32;
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum AcsHkIds { pub enum AocsHkIds {
TestMgmSet = 1, TestAocsSet = 1,
TestMgmSet = 2,
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -14,3 +34,154 @@ pub enum HkRequest {
Disable(AddressableId), Disable(AddressableId),
ModifyCollectionInterval(AddressableId, CollectionIntervalFactor), ModifyCollectionInterval(AddressableId, CollectionIntervalFactor),
} }
#[derive(Serialize, Deserialize)]
pub struct AocsSensorData {
mgm_data: MGMData, // Voltage for 3 axis
css_data: [f64; 18], // Voltage for 18 sun sensors
str_data: [f64; 4], // Quaternion for position of satellite
}
impl AocsSensorData {
pub fn new() -> AocsSensorData {
let mgm_data = MGMData::default();
let css_data = [0.0; 18];
let str_data = [0.0; 4];
AocsSensorData {
mgm_data,
css_data,
str_data,
}
}
pub fn update_mgm_data(&mut self, mgm_data: &Arc<Mutex<MGMData>>) {
let data = mgm_data.lock().unwrap();
self.mgm_data = *data;
}
pub fn write_css_data(&mut self, css_data: [f64; 18]) {
self.css_data = css_data;
}
pub fn write_str_data(&mut self, str_data: [f64; 4]) {
self.str_data = str_data;
}
pub fn get_mgm_data(&mut self) -> MGMData {
self.mgm_data
}
pub fn read_css_data(&mut self) -> [f64; 18] {
self.css_data
}
pub fn read_str_data(&mut self) -> [f64; 4] {
self.str_data
}
}
pub struct AocsHousekeeper {
sensor_data_pool: Arc<Mutex<AocsSensorData>>,
action_rx: Receiver<RequestWithToken>,
seq_count_provider: SeqCountProviderSyncClonable,
aocs_tm_store: TmStore,
aocs_tm_funnel_tx: Sender<StoreAddr>,
verif_reporter: VerificationReporterWithSender<StdVerifSenderError>,
}
impl AocsHousekeeper {
pub fn new(
sensor_data_pool: Arc<Mutex<AocsSensorData>>,
action_rx: Receiver<RequestWithToken>,
seq_count_provider: SeqCountProviderSyncClonable,
aocs_tm_store: TmStore,
aocs_tm_funnel_tx: Sender<StoreAddr>,
verif_reporter: VerificationReporterWithSender<StdVerifSenderError>,
) -> AocsHousekeeper {
AocsHousekeeper {
sensor_data_pool,
action_rx,
seq_count_provider,
aocs_tm_store,
aocs_tm_funnel_tx,
verif_reporter,
}
}
pub fn handle_hk_request(&mut self) {
let mut time_stamp_buf: [u8; 7] = [0; 7];
if let Ok(request_with_token) = self.action_rx.try_recv() {
if let Request::HkRequest(hk_req) = request_with_token.0 {
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
let start_token = self //implement this for verification
.verif_reporter
.start_success(request_with_token.1, Some(&time_stamp_buf))
.expect("Error sending start success");
if let Ok(()) = match hk_req {
HkRequest::OneShot(id) => self.one_shot_hk(id),
HkRequest::Enable(id) => self.enable_hk(id),
HkRequest::Disable(id) => self.disable_hk(id),
HkRequest::ModifyCollectionInterval(_id, _collection_interval) => Ok(()),
} {
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
self.verif_reporter
.completion_success(start_token, Some(&time_stamp_buf))
.expect("Error sending completion success");
} else {
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
self.verif_reporter
.completion_failure(
start_token,
FailParams::new(
Some(&time_stamp_buf),
&hk_err::UNKNOWN_TARGET_ID,
None,
),
)
.expect("Error sending completion success");
}
}
}
}
pub fn one_shot_hk(&mut self, id: AddressableId) -> Result<(), ()> {
let json_string = self.aocs_data_to_str();
self.send_hk_packet(id, &json_string);
Ok(())
}
pub fn enable_hk(&mut self, _id: AddressableId) -> Result<(), ()> {
Ok(())
}
pub fn disable_hk(&mut self, _id: AddressableId) -> Result<(), ()> {
Ok(())
}
pub fn aocs_data_to_str(&mut self) -> String {
let pool = self.sensor_data_pool.lock().unwrap();
serde_json::to_string(pool.deref()).unwrap()
}
pub fn send_hk_packet(&mut self, id: AddressableId, data: &str) {
let mut time_stamp_buf: [u8; 7] = [0; 7];
let mut huge_buf: [u8; 8192] = [0; 8192];
let mut sp_header =
SpHeader::tm_unseg(0x02, self.seq_count_provider.get_and_increment(), 0).unwrap();
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
let mut len = id.write_to_be_bytes(&mut huge_buf).unwrap();
huge_buf[8..data.len() + 8].copy_from_slice(data.as_bytes());
len += data.len();
let tm_sec_header =
PusTmSecondaryHeader::new_simple(3, Subservice::TmHkPacket as u8, &time_stamp_buf);
let hk_tm = PusTm::new(&mut sp_header, tm_sec_header, Some(&huge_buf[0..len]), true);
let addr = self.aocs_tm_store.add_pus_tm(&hk_tm);
self.aocs_tm_funnel_tx.send(addr).expect("sending failed");
}
}

View File

@ -1,18 +1,24 @@
#![allow(dead_code)]
#![allow(unused_variables)]
// remove this, just here for now since application isn't fully developed
mod action; mod action;
mod aocs; mod aocs;
mod aocs_handler;
mod cam; mod cam;
#[cfg(feature = "can")]
mod can; mod can;
mod can_ids; mod can_ids;
mod ccsds; mod ccsds;
mod pld_handler;
mod hk; mod hk;
mod logger; mod logger;
mod pld_handler;
mod power_handler;
mod pus; mod pus;
mod requests; mod requests;
mod tmtc; mod tmtc;
mod pcdu;
use crate::requests::{Request, RequestWithToken}; use crate::requests::{RequestWithToken};
use crate::tmtc::{ use crate::tmtc::{
core_tmtc_task, OtherArgs, PusTcSource, TcArgs, TcStore, TmArgs, TmFunnel, TmStore, PUS_APID, core_tmtc_task, OtherArgs, PusTcSource, TcArgs, TcStore, TmArgs, TmFunnel, TmStore, PUS_APID,
}; };
@ -23,37 +29,33 @@ use satrs_core::event_man::{
use satrs_core::events::EventU32; use satrs_core::events::EventU32;
use satrs_core::pool::{LocalPool, PoolCfg, StoreAddr}; use satrs_core::pool::{LocalPool, PoolCfg, StoreAddr};
use satrs_core::pus::event_man::{ use satrs_core::pus::event_man::{
DefaultPusMgmtBackendProvider, EventReporter, EventRequestWithToken, DefaultPusMgmtBackendProvider, EventReporter, EventRequestWithToken, PusEventDispatcher,
PusEventDispatcher,
}; };
use satrs_core::pus::verification::{ use satrs_core::pus::verification::{
MpscVerifSender, VerificationReporterCfg, VerificationReporterWithSender, MpscVerifSender, VerificationReporterCfg, VerificationReporterWithSender,
}; };
use satrs_core::pus::{EcssTmErrorWithSend, EcssTmSenderCore}; use satrs_core::pus::{EcssTmErrorWithSend, EcssTmSenderCore};
use satrs_core::seq_count::{ use satrs_core::seq_count::SeqCountProviderSyncClonable;
SeqCountProviderSyncClonable, use satrs_core::{spacepackets::tm::PusTm};
};
use satrs_core::{
spacepackets::time::cds::TimeProvider,
spacepackets::time::TimeWriter,
spacepackets::tm::{PusTm},
};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use crate::can_ids::{can_id_to_package_id, DeviceId, load_package_ids, PackageId, PackageModel, ThreadId}; use crate::can_ids::{
use embedded_can::{Id, StandardId}; load_package_ids, DeviceId, PackageModel, ThreadId,
use log::{info, warn}; };
use log::{info};
use satrs_core::power::{SwitchId, SwitchState};
use std::collections::HashMap; use std::collections::HashMap;
use std::net::{IpAddr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
use std::sync::mpsc::{channel}; use std::sync::mpsc::channel;
use std::sync::{mpsc, Arc, RwLock, Mutex}; use std::sync::{mpsc, Arc, Mutex, RwLock};
use std::thread; use std::thread;
use satrs_core::power::{SwitchId, SwitchState};
//use libc::time64_t; //use libc::time64_t;
use crate::action::ActionRequest; use crate::aocs_handler::{MGMData, MGMHandler};
use crate::cam::CameraRequest; #[cfg(feature = "can")]
use crate::pld_handler::{CameraHandler, core_pld_task}; use crate::can::CanTxHandler;
use crate::pcdu::{core_power_task, PowerSwitcher}; use crate::hk::{AocsHousekeeper, AocsSensorData};
use crate::pld_handler::{core_pld_task};
use crate::power_handler::{core_power_task, PowerSwitcher};
#[derive(Clone)] #[derive(Clone)]
struct EventTmSender { struct EventTmSender {
@ -82,9 +84,8 @@ impl EcssTmSenderCore for EventTmSender {
} }
fn main() { fn main() {
println!("Running SESPSat OBSW");
logger::setup_logger().unwrap(); logger::setup_logger().unwrap();
info!("Running DemoSat OBSW!");
let tm_pool = LocalPool::new(PoolCfg::new(vec![ let tm_pool = LocalPool::new(PoolCfg::new(vec![
(30, 32), (30, 32),
@ -136,19 +137,19 @@ fn main() {
let mut event_man = EventManagerWithMpscQueue::new(Box::new(event_recv)); let mut event_man = EventManagerWithMpscQueue::new(Box::new(event_recv));
let event_reporter = EventReporter::new(PUS_APID, 128).unwrap(); let event_reporter = EventReporter::new(PUS_APID, 128).unwrap();
let pus_tm_backend = DefaultPusMgmtBackendProvider::<EventU32>::default(); let pus_tm_backend = DefaultPusMgmtBackendProvider::<EventU32>::default();
let mut pus_event_dispatcher = let pus_event_dispatcher =
PusEventDispatcher::new(event_reporter, Box::new(pus_tm_backend)); PusEventDispatcher::new(event_reporter, Box::new(pus_tm_backend));
let (pus_event_man_tx, pus_event_man_rx) = channel(); let (pus_event_man_tx, pus_event_man_rx) = channel();
let pus_event_man_send_provider = MpscEventU32SendProvider::new(1, pus_event_man_tx); let pus_event_man_send_provider = MpscEventU32SendProvider::new(1, pus_event_man_tx);
let mut reporter_event_handler = verif_reporter.clone(); let reporter_event_handler = verif_reporter.clone();
let mut reporter_aocs = verif_reporter.clone(); let reporter_aocs = verif_reporter.clone();
let mut reporter_pld = verif_reporter.clone(); let mut reporter_pld = verif_reporter.clone();
event_man.subscribe_all(pus_event_man_send_provider.id()); event_man.subscribe_all(pus_event_man_send_provider.id());
let mut request_map = HashMap::new(); let mut request_map = HashMap::new();
let (acs_thread_tx, acs_thread_rx) = channel::<RequestWithToken>(); let (aocs_thread_tx, aocs_thread_rx) = channel::<RequestWithToken>();
let (pld_thread_tx, pld_thread_rx) = channel::<RequestWithToken>(); let (pld_thread_tx, pld_thread_rx) = channel::<RequestWithToken>();
request_map.insert(RequestTargetId::AcsSubsystem as u32, acs_thread_tx); request_map.insert(RequestTargetId::AcsSubsystem as u32, aocs_thread_tx);
request_map.insert(RequestTargetId::PldSubsystem as u32, pld_thread_tx); request_map.insert(RequestTargetId::PldSubsystem as u32, pld_thread_tx);
//add here receivers for tmtc task to send requests to //add here receivers for tmtc task to send requests to
//request_map.insert(RequestTargetId::CanTask as u32, can_thread_tx); //request_map.insert(RequestTargetId::CanTask as u32, can_thread_tx);
@ -189,27 +190,39 @@ fn main() {
// get package id hashmap // get package id hashmap
let package_ids_rx = load_package_ids(); let package_ids_rx = load_package_ids();
let socket0 = can::CanRxHandler::new_socket("can0", can_senders, package_ids_rx).unwrap();
info!("Starting TMTC task"); info!("Starting TMTC task");
let builder0 = thread::Builder::new().name("TMTCThread".into()); let builder0 = thread::Builder::new().name("TMTCThread".into());
let jh0 = builder0.spawn(move || { let jh0 = builder0.spawn(move || {
core_tmtc_task(core_args, tc_args, tm_args); core_tmtc_task(core_args, tc_args, tm_args);
}); });
let (can_tx_sender, can_tx_receiver) = channel();
#[cfg(feature = "can")]
let mut can_rx_socket = can::CanRxHandler::new_socket("can0", can_senders.clone(), package_ids_rx.clone()).unwrap();
#[cfg(feature = "can")]
info!("Starting CAN Socket listening task"); info!("Starting CAN Socket listening task");
let builder1 = thread::Builder::new().name("CanRxHandler".into()); let builder1 = thread::Builder::new().name("CanRxHandler".into());
let jh1 = builder1.spawn(move || loop { let jh1 = builder1.spawn(move || loop {
let frame = socket0.rx_socket(); #[cfg(feature = "can")]
if let Some(frame) = frame { can_rx_socket.process_incoming();
let forward = socket0.forward_frame(frame); });
}
#[cfg(feature = "can")]
let mut can_tx_socket = CanTxHandler::new_socket("can0", package_ids_rx.clone(), can_tx_receiver).unwrap();
#[cfg(feature = "can")]
info!("Starting CAN Socket writing task");
let builder_can_tx = thread::Builder::new().name("TxHandler".into());
let jh_can_tx = builder_can_tx.spawn( move || loop {
#[cfg(feature = "can")]
can_tx_socket.process_incoming();
}); });
let (pcdu_tx, pcdu_rx) = mpsc::channel::<(SwitchId, SwitchState)>(); let (pcdu_tx, pcdu_rx) = mpsc::channel::<(SwitchId, SwitchState)>();
let pcdu_can_tx = let pcdu_can_tx_sender =
can::CanTxHandler::new_socket("can0", ThreadId::PowerThread, load_package_ids()).unwrap(); can_tx_sender.clone();
let mut device_state_map = HashMap::new(); let mut device_state_map = HashMap::new();
for id in DeviceId::iter() { for id in DeviceId::iter() {
@ -217,126 +230,42 @@ fn main() {
} }
let clonable_device_state_map = Arc::new(Mutex::new(device_state_map)); let clonable_device_state_map = Arc::new(Mutex::new(device_state_map));
let mut power_switcher = PowerSwitcher::new(pcdu_tx, clonable_device_state_map.clone()); let power_switcher = PowerSwitcher::new(pcdu_tx, clonable_device_state_map.clone());
info!("Starting power task"); info!("Starting power task");
let builder2 = thread::Builder::new().name("PowerThread".into()); let builder2 = thread::Builder::new().name("PowerThread".into());
let jh2 = builder2.spawn(move || { let jh2 = builder2.spawn(move || {
core_power_task(pcdu_rx, pcdu_can_tx, power_can_rx, clonable_device_state_map.clone()); core_power_task(
}); pcdu_rx,
pcdu_can_tx_sender,
power_can_rx,
let package_map_aocs_tx = load_package_ids(); clonable_device_state_map.clone(),
let aocs_tm_funnel_tx = tm_funnel_tx.clone();
let mut aocs_tm_store = tm_store.clone();
/*
// AOCS Thread
let socket1 =
can::CanTxHandler::new_socket("can0", ThreadId::AOCSThread, package_map_aocs_tx).unwrap();
info!("Starting AOCS receiving thread");
let builder2 = thread::Builder::new().name("AOCSThread".into());
let jh2 = builder2.spawn(move || {
let mut time_stamp_buf: [u8; 7] = [0; 7];
let mut huge_buf: [u8; 8192] = [0; 8192];
let data: [u8; 3] = [1, 2, 3];
let current_mgm_data = MgmData::default();
//let current_mgt_data = MgtData::default();
//let current_
loop {
// device handling
//info!("Sending {:?}", PackageId::AOCSControlMGT1);
//socket1.tx_socket(PackageId::AOCSControlMGT1, &data);
//info!("Waiting for {:?}", PackageId::AOCSDataMGM1);
let msg = aocs_can_rx.try_recv();
//current_mgm_data.x = new_data
match aocs_can_rx.try_recv() {
Ok(package) => match package.package_id() {
_ => warn!("Incorrect Id"),
},
Err(_) => {}
}
// telecommand handling
match acs_thread_rx.try_recv() {
Ok(request_with_token) => {
match request_with_token.0 {
Request::HkRequest(hk_req) => {
match hk_req {
HkRequest::OneShot(id) => {
assert_eq!(id.target_id, RequestTargetId::AcsSubsystem as u32);
if id.unique_id == 0 {
let mut sp_header = SpHeader::tm_unseg(
0x02,
aocs_seq_count_provider.get_and_increment(),
0,
)
.unwrap();
let cds_stamp =
TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf);
let mut len = id.write_to_be_bytes(&mut huge_buf).unwrap();
let json_string = "asdf";
huge_buf[8..json_string.len() + 8]
.copy_from_slice(json_string.as_bytes());
len += json_string.len();
let tm_sec_header = PusTmSecondaryHeader::new_simple(
3,
Subservice::TmHkPacket as u8,
&time_stamp_buf,
); );
let hk_tm = PusTm::new(
&mut sp_header,
tm_sec_header,
Some(&huge_buf[0..len]),
true,
);
let addr = aocs_tm_store.add_pus_tm(&hk_tm);
aocs_tm_funnel_tx.send(addr).expect("sending failed");
/* let start_token = self //implement this for verification
.verif_reporter
.start_success(token, &self.time_stamp)
.expect("Error sending start success");
self.tm_tx
.send(addr)
.expect("Sending TM to TM funnel failed");
self.verif_reporter
.completion_success(start_token, &self.time_stamp)
.expect("Error sending completion success");
*/
}
}
HkRequest::Enable(_) => {}
HkRequest::Disable(_) => {}
HkRequest::ModifyCollectionInterval(_, _) => {}
}
}
_ => {}
}
}
Err(_) => {}
}
}
}); });
*/
let package_map_pld_tx = load_package_ids(); let package_map_pld_tx = load_package_ids();
let pld_tm_funnel_tx = tm_funnel_tx.clone(); let pld_tm_funnel_tx = tm_funnel_tx.clone();
let mut pld_tm_store = tm_store.clone(); let pld_tm_store = tm_store.clone();
let PLDCanSocket = let pld_can_tx_sender =
can::CanTxHandler::new_socket("can0", ThreadId::PLDThread, package_map_pld_tx).unwrap(); can_tx_sender.clone();
let power_switcher_pld = power_switcher.clone();
//let mut pcdu_tx_clone = pcdu_tx.clone(); //let mut pcdu_tx_clone = pcdu_tx.clone();
println!("Starting Payload Handling task"); info!("Starting Payload Handling task");
let builder3 = thread::Builder::new().name("PLDThread".into()); let builder3 = thread::Builder::new().name("PLDThread".into());
let jh3 = builder3.spawn(move || { let jh3 = builder3.spawn(move || {
core_pld_task(power_switcher.clone(), pld_thread_rx, pld_can_rx, &mut reporter_pld); core_pld_task(
power_switcher_pld.clone(),
pld_thread_rx,
pld_can_rx,
pld_can_tx_sender,
&mut reporter_pld,
);
}); });
println!("Starting TM funnel task"); info!("Starting TM funnel task");
let builder4 = thread::Builder::new().name("TMFunnelThread".into()); let builder4 = thread::Builder::new().name("TMFunnelThread".into());
let jh4 = builder4.spawn(move || { let jh4 = builder4.spawn(move || {
let tm_funnel = TmFunnel { let tm_funnel = TmFunnel {
@ -353,15 +282,58 @@ fn main() {
} }
}); });
let package_map_aocs_tx = load_package_ids();
let aocs_tm_funnel_tx = tm_funnel_tx.clone();
let aocs_tm_store = tm_store.clone();
let mgm_shared_data: Arc<Mutex<MGMData>> = Arc::default();
let aocs_sensor_data = Arc::new(Mutex::new(AocsSensorData::new()));
let (aocs_mode_tx, aocs_mode_rx) = channel();
let (mgm_action_tx, mgm_action_rx) = channel();
let power_switcher_aocs = power_switcher.clone();
info!("Starting AOCS task");
let builder5 = thread::Builder::new().name("AOCSThread".into());
let jh5 = builder5.spawn(move || {
let mut mgm_handler = MGMHandler::new(power_switcher_aocs.clone(), DeviceId::MGM1, can_tx_sender.clone(), aocs_can_rx, aocs_mode_rx, mgm_action_rx);
let aocs_sensor_data = Arc::new(Mutex::new(AocsSensorData::new()));
let mut aocs_housekeeper = AocsHousekeeper::new(
aocs_sensor_data.clone(),
aocs_thread_rx,
aocs_seq_count_provider,
aocs_tm_store,
aocs_tm_funnel_tx,
reporter_aocs,
);
loop {
mgm_handler.periodic_op();
let mut locked_sensor_data = aocs_sensor_data.lock().unwrap();
locked_sensor_data.update_mgm_data(&mgm_handler.get_data_ref());
drop(locked_sensor_data);
aocs_housekeeper.handle_hk_request();
}
});
jh0.unwrap() jh0.unwrap()
.join() .join()
.expect("Joining UDP TMTC server thread failed"); .expect("Joining UDP TMTC server thread failed");
jh1.unwrap() jh1.unwrap()
.join() .join()
.expect("Joining CAN Bus Listening thread failed"); .expect("Joining CAN Bus Listening thread failed");
jh_can_tx.unwrap()
.join()
.expect("Joining CAN Bus Writing thread failed");
jh2.unwrap().join().expect("Joining power thread failed"); jh2.unwrap().join().expect("Joining power thread failed");
jh3.unwrap().join().expect("Joining PLD thread failed"); jh3.unwrap().join().expect("Joining PLD thread failed");
jh4.unwrap().join().expect("Joining TM funnel thread failed"); jh4.unwrap()
.join()
.expect("Joining TM funnel thread failed");
jh5.unwrap().join().expect("Joining AOCS thread failed");
} }
#[derive(Default)] #[derive(Default)]
struct MgmData { struct MgmData {

View File

@ -1,17 +1,15 @@
use std::sync::mpsc; use crate::action::ActionRequest;
use std::sync::mpsc::{Receiver, Sender, TryRecvError}; use crate::can_ids::{DeviceId, PackageId, PackageModel};
use log::info; use crate::power_handler::{DeviceState, PowerSwitcher};
use satrs_core::power::{PowerSwitcherCommandSender, PowerSwitchInfo, SwitchId, SwitchState}; use crate::requests::{Request, RequestWithToken};
use eurosim_obsw::RequestTargetId;
use log::{debug};
use satrs_core::power::{PowerSwitchInfo, PowerSwitcherCommandSender, SwitchId};
use satrs_core::pus::verification::{StdVerifSenderError, VerificationReporterWithSender}; use satrs_core::pus::verification::{StdVerifSenderError, VerificationReporterWithSender};
use satrs_core::spacepackets::time::cds::TimeProvider; use satrs_core::spacepackets::time::cds::TimeProvider;
use satrs_core::spacepackets::time::TimeWriter; use satrs_core::spacepackets::time::TimeWriter;
use eurosim_obsw::RequestTargetId; use std::sync::mpsc;
use crate::action::ActionRequest; use std::sync::mpsc::{Receiver, Sender};
use crate::can::CanTxHandler;
use crate::can_ids::{DeviceId, load_package_ids, PackageId, PackageModel, ThreadId};
use crate::pld_handler::CameraMode::PictureRequest;
use crate::pcdu::{DeviceState, PowerSwitcher};
use crate::requests::{Request, RequestWithToken};
#[derive(Debug, PartialEq, Copy, Clone)] #[derive(Debug, PartialEq, Copy, Clone)]
pub enum CameraMode { pub enum CameraMode {
@ -27,22 +25,40 @@ pub struct CameraHandler {
camera_device_id: DeviceId, camera_device_id: DeviceId,
camera_switch_id: SwitchId, camera_switch_id: SwitchId,
device_state: DeviceState, device_state: DeviceState,
can_tx: CanTxHandler, can_tx: Sender<PackageModel>,
can_rx: Receiver<PackageModel>, can_rx: Receiver<PackageModel>,
mode: CameraMode, mode: CameraMode,
mode_rx: Receiver<CameraMode>, mode_rx: Receiver<CameraMode>,
action_rx: Receiver<RequestWithToken>,
} }
impl CameraHandler { impl CameraHandler {
pub fn new(power_switcher: PowerSwitcher, camera_device_id: DeviceId, can_tx: CanTxHandler, can_rx: Receiver<PackageModel>, mode_rx: Receiver<CameraMode>) -> CameraHandler { pub fn new(
power_switcher: PowerSwitcher,
camera_device_id: DeviceId,
can_tx: Sender<PackageModel>,
can_rx: Receiver<PackageModel>,
mode_rx: Receiver<CameraMode>,
action_rx: Receiver<RequestWithToken>,
) -> CameraHandler {
let camera_switch_id = camera_device_id as u16; let camera_switch_id = camera_device_id as u16;
CameraHandler{power_switcher, camera_device_id, camera_switch_id, device_state: DeviceState::Off, can_tx, can_rx, mode: CameraMode::Idle, mode_rx} CameraHandler {
power_switcher,
camera_device_id,
camera_switch_id,
device_state: DeviceState::Off,
can_tx,
can_rx,
mode: CameraMode::Idle,
mode_rx,
action_rx,
}
} }
pub fn set_mode(&mut self, mode: CameraMode) { pub fn set_mode(&mut self, mode: CameraMode) {
if self.mode == CameraMode::Idle{ if self.mode == CameraMode::Idle {
if mode == CameraMode::PictureRequest { if mode == CameraMode::PictureRequest {
self.mode = PictureRequest; self.mode = CameraMode::PictureRequest;
} }
} }
} }
@ -51,84 +67,17 @@ impl CameraHandler {
self.mode self.mode
} }
pub fn periodic_op(&mut self) { pub fn handle_mode_requests(&mut self) {
// Camera Device Handler State Machine match self.mode_rx.try_recv() {
Ok(mode) => {
self.set_mode(mode);
}
Err(_) => {}
}
}
match self.mode { /*pub fn handle_action_requests(&mut self) {
CameraMode::Idle => {} match self.action_rx.try_recv() {
CameraMode::PictureRequest => {
if self.device_state == DeviceState::Off {
self.power_switcher.send_switch_on_cmd(self.camera_switch_id).expect("sending switch cmd failed");
self.device_state = DeviceState::SwitchingPower;
info!("switching power");
}
if self.device_state == DeviceState::SwitchingPower {
if self.power_switcher.get_is_switch_on(self.camera_switch_id).expect("reading switch state failed") {
self.device_state = DeviceState::On;
info!("device on");
}
}
if self.device_state == DeviceState::On {
self.can_tx.tx_socket(PackageId::CameraImageRequest, &[1]);
info!("sent camera request");
self.mode = CameraMode::Verification;
}
}
CameraMode::Verification => {
if self.device_state == DeviceState::On {
info!("waiting for image request confirmation");
if let Ok(msg) = self.can_rx.recv() {
if msg.package_id() == PackageId::CameraImageRequestConfirmation {
self.mode = CameraMode::Start;
}
}
}
}
CameraMode::Start => {
if self.device_state == DeviceState::On {
info!("waiting for image start confirmation");
if let Ok(msg) = self.can_rx.recv() {
if msg.package_id() == PackageId::CameraImageExecutionStart {
self.mode = CameraMode::End;
}
}
}
}
CameraMode::End => {
if self.device_state == DeviceState::On {
info!("waiting for image end confirmation");
if let Ok(msg) = self.can_rx.recv() {
if msg.package_id() == PackageId::CameraImageExectutionEnd {
self.power_switcher.send_switch_off_cmd(self.camera_switch_id).expect("sending switch command failed");
self.device_state = DeviceState::SwitchingPower;
info!("switching power");
}
}
}
if self.device_state == DeviceState::SwitchingPower {
if !self.power_switcher.get_is_switch_on(self.camera_switch_id).expect("reading switch state failed") {
self.device_state = DeviceState::Off;
info!("device off");
}
}
if self.device_state == DeviceState::Off {
self.mode = CameraMode::Idle;
}
}
}
}
}
pub fn core_pld_task(power_switcher: PowerSwitcher, pld_thread_rx: Receiver<RequestWithToken>, pld_can_rx: Receiver<PackageModel>, reporter_pld: &mut VerificationReporterWithSender<StdVerifSenderError>) {
let (camera_mode_tx, camera_mode_rx) = mpsc::channel();
let camera_can_tx =
CanTxHandler::new_socket("can0", ThreadId::PLDThread, load_package_ids()).unwrap();
let mut camera_handler = CameraHandler::new(power_switcher, DeviceId::Camera, camera_can_tx, pld_can_rx, camera_mode_rx);
let mut time_stamp_buf: [u8; 7] = [0; 7];
loop {
match pld_thread_rx.try_recv() {
Ok(request_with_token) => { Ok(request_with_token) => {
match request_with_token.0 { match request_with_token.0 {
Request::ActionRequest(action_id) => { Request::ActionRequest(action_id) => {
@ -144,11 +93,13 @@ pub fn core_pld_task(power_switcher: PowerSwitcher, pld_thread_rx: Receiver<Requ
.start_success(request_with_token.1, Some(&time_stamp_buf)) .start_success(request_with_token.1, Some(&time_stamp_buf))
.expect("Error sending start success."); .expect("Error sending start success.");
info!("{:?}", camera_handler.get_mode()); debug!("{:?}", camera_handler.get_mode());
while camera_handler.get_mode() != CameraMode::Idle { while camera_handler.get_mode() != CameraMode::Idle {
camera_handler.periodic_op(); camera_handler.periodic_op();
} }
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
// send end verification with token // send end verification with token
reporter_pld reporter_pld
.completion_success( .completion_success(
@ -168,4 +119,147 @@ pub fn core_pld_task(power_switcher: PowerSwitcher, pld_thread_rx: Receiver<Requ
} }
} }
*/
pub fn take_picture(&mut self) {}
pub fn periodic_op(&mut self) {
// Camera Device Handler State Machine
match self.mode {
CameraMode::Idle => {}
CameraMode::PictureRequest => {
if self.device_state == DeviceState::Off {
self.power_switcher
.send_switch_on_cmd(self.camera_switch_id)
.expect("sending switch cmd failed");
self.device_state = DeviceState::SwitchingPower;
debug!("switching power");
}
if self.device_state == DeviceState::SwitchingPower {
if self
.power_switcher
.get_is_switch_on(self.camera_switch_id)
.expect("reading switch state failed")
{
self.device_state = DeviceState::On;
debug!("device on");
}
}
if self.device_state == DeviceState::On {
self.can_tx.send(PackageModel::new(PackageId::CameraImageRequest, &[1]).unwrap()).unwrap();
debug!("sent camera request");
self.mode = CameraMode::Verification;
}
}
CameraMode::Verification => {
if self.device_state == DeviceState::On {
debug!("waiting for image request confirmation");
if let Ok(msg) = self.can_rx.recv() {
if msg.package_id() == PackageId::CameraImageRequestConfirmation {
self.mode = CameraMode::Start;
}
}
}
}
CameraMode::Start => {
if self.device_state == DeviceState::On {
debug!("waiting for image start confirmation");
if let Ok(msg) = self.can_rx.recv() {
if msg.package_id() == PackageId::CameraImageExecutionStart {
self.mode = CameraMode::End;
}
}
}
}
CameraMode::End => {
if self.device_state == DeviceState::On {
debug!("waiting for image end confirmation");
if let Ok(msg) = self.can_rx.recv() {
if msg.package_id() == PackageId::CameraImageExectutionEnd {
self.power_switcher
.send_switch_off_cmd(self.camera_switch_id)
.expect("sending switch command failed");
self.device_state = DeviceState::SwitchingPower;
debug!("switching power");
}
}
}
if self.device_state == DeviceState::SwitchingPower {
if !self
.power_switcher
.get_is_switch_on(self.camera_switch_id)
.expect("reading switch state failed")
{
self.device_state = DeviceState::Off;
debug!("device off");
}
}
if self.device_state == DeviceState::Off {
self.mode = CameraMode::Idle;
}
}
}
}
}
pub fn core_pld_task(
power_switcher: PowerSwitcher,
pld_thread_rx: Receiver<RequestWithToken>,
pld_can_rx: Receiver<PackageModel>,
pld_can_tx: Sender<PackageModel>,
reporter_pld: &mut VerificationReporterWithSender<StdVerifSenderError>,
) {
let (_camera_mode_tx, camera_mode_rx) = mpsc::channel();
let (_action_tx, action_rx) = mpsc::channel();
let mut camera_handler = CameraHandler::new(
power_switcher,
DeviceId::Camera,
pld_can_tx,
pld_can_rx,
camera_mode_rx,
action_rx,
);
let mut time_stamp_buf: [u8; 7] = [0; 7];
loop {
match pld_thread_rx.try_recv() {
Ok(request_with_token) => {
match request_with_token.0 {
Request::ActionRequest(action_id) => {
match action_id {
ActionRequest::ImageRequest(target_id) => {
assert_eq!(target_id, RequestTargetId::PldSubsystem);
camera_handler.set_mode(CameraMode::PictureRequest);
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
// send start verification and get token
let start_token = reporter_pld
.start_success(request_with_token.1, Some(&time_stamp_buf))
.expect("Error sending start success.");
debug!("{:?}", camera_handler.get_mode());
while camera_handler.get_mode() != CameraMode::Idle {
camera_handler.periodic_op();
}
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
// send end verification with token
reporter_pld
.completion_success(start_token, Some(&time_stamp_buf))
.expect("Error sending start success.");
}
ActionRequest::OrientationRequest(_) => {}
ActionRequest::PointingRequest(_) => {}
}
}
_ => {}
}
}
Err(_) => {}
}
}
} }

View File

@ -1,13 +1,14 @@
use std::collections::HashMap;
use std::sync::mpsc::{Receiver, Sender};
use satrs_core::power::{PowerSwitcherCommandSender, PowerSwitchInfo, PowerSwitchProvider, SwitchId, SwitchState};
use crate::can::{CanTxHandler};
use crate::can_ids::{DeviceId, PackageId, PackageModel}; use crate::can_ids::{DeviceId, PackageId, PackageModel};
use log::{debug};
use satrs_core::power::{
PowerSwitchInfo, PowerSwitchProvider, PowerSwitcherCommandSender, SwitchId, SwitchState,
};
use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use std::vec; use std::vec;
use log::info;
pub use strum::IntoEnumIterator; // 0.17.1 pub use strum::IntoEnumIterator; // 0.17.1
pub use strum_macros::EnumIter; // 0.17.1 pub use strum_macros::EnumIter; // 0.17.1
@ -28,14 +29,20 @@ pub struct PowerSwitcher {
pub struct PCDU { pub struct PCDU {
switch_rx: Receiver<(SwitchId, SwitchState)>, switch_rx: Receiver<(SwitchId, SwitchState)>,
can_tx: CanTxHandler, can_tx: Sender<PackageModel>,
can_rx: Receiver<PackageModel>, can_rx: Receiver<PackageModel>,
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>, device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
} }
impl PowerSwitcher { impl PowerSwitcher {
pub fn new(switch_tx: Sender<(SwitchId, SwitchState)>, device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>) -> PowerSwitcher { pub fn new(
PowerSwitcher{switch_tx, device_state_map} switch_tx: Sender<(SwitchId, SwitchState)>,
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
) -> PowerSwitcher {
PowerSwitcher {
switch_tx,
device_state_map,
}
} }
} }
@ -44,16 +51,16 @@ impl PowerSwitcherCommandSender for PowerSwitcher {
fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> { fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> {
return match self.switch_tx.send((switch_id, SwitchState::On)) { return match self.switch_tx.send((switch_id, SwitchState::On)) {
Ok(_) => {Ok(())} Ok(_) => Ok(()),
Err(_) => {Err(())} Err(_) => Err(()),
} };
} }
fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> { fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> {
return match self.switch_tx.send((switch_id, SwitchState::Off)) { return match self.switch_tx.send((switch_id, SwitchState::Off)) {
Ok(_) => {Ok(())} Ok(_) => Ok(()),
Err(_) => {Err(())} Err(_) => Err(()),
} };
} }
} }
@ -67,11 +74,10 @@ impl PowerSwitchInfo for PowerSwitcher {
Ok(*state) Ok(*state)
} else { } else {
Err(()) Err(())
} };
} else { } else {
Err(()) Err(())
} }
} }
fn switch_delay_ms(&self) -> u32 { fn switch_delay_ms(&self) -> u32 {
@ -84,81 +90,85 @@ impl PowerSwitchProvider for PowerSwitcher {
} }
impl PCDU { impl PCDU {
pub fn new(switch_rx: Receiver<(SwitchId, SwitchState)>, can_tx: CanTxHandler, can_rx: Receiver<PackageModel>, device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>) -> PCDU{ pub fn new(
PCDU{switch_rx, can_tx, can_rx, device_state_map} switch_rx: Receiver<(SwitchId, SwitchState)>,
can_tx: Sender<PackageModel>,
can_rx: Receiver<PackageModel>,
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
) -> PCDU {
PCDU {
switch_rx,
can_tx,
can_rx,
device_state_map,
}
} }
pub fn send_power_on(&mut self, switch_id: SwitchId) -> Result<(), ()> { pub fn send_power_on(&mut self, switch_id: SwitchId) -> Result<(), ()> {
return if let Ok(dev_id) = DeviceId::try_from(switch_id) { return if let Ok(dev_id) = DeviceId::try_from(switch_id) {
let dev_id_bytes = dev_id as u8; let dev_id_bytes = dev_id as u8;
let buf: &[u8] = &dev_id_bytes.to_be_bytes(); let buf: &[u8] = &dev_id_bytes.to_be_bytes();
self.can_tx.tx_socket(PackageId::DevicePowerOnRequest, buf); self.can_tx.send(PackageModel::new(PackageId::DevicePowerOnRequest, buf).unwrap()).unwrap();
let mut map_lock = self.device_state_map.lock().unwrap(); let mut map_lock = self.device_state_map.lock().unwrap();
*map_lock.get_mut(&dev_id).unwrap() = SwitchState::Unknown; *map_lock.get_mut(&dev_id).unwrap() = SwitchState::Unknown;
self.can_rx.recv(); // TODO: potentially change bus logic -> remove acceptance and verification of power off/on, since status is simply called in next step anyway
self.can_rx.recv(); self.can_rx.recv().unwrap();
self.can_rx.recv().unwrap();
Ok(()) Ok(())
} else { } else {
Err(()) Err(())
} };
} }
pub fn send_power_off(&mut self, switch_id: SwitchId) -> Result<(), ()> { pub fn send_power_off(&mut self, switch_id: SwitchId) -> Result<(), ()> {
return if let Ok(dev_id) = DeviceId::try_from(switch_id) { return if let Ok(dev_id) = DeviceId::try_from(switch_id) {
let dev_id_bytes = dev_id as u8; let dev_id_bytes = dev_id as u8;
let buf: &[u8] = &dev_id_bytes.to_be_bytes(); let buf: &[u8] = &dev_id_bytes.to_be_bytes();
self.can_tx.tx_socket(PackageId::DevicePowerOffRequest, buf); self.can_tx.send(PackageModel::new(PackageId::DevicePowerOffRequest, buf).unwrap()).unwrap();
let mut map_lock = self.device_state_map.lock().unwrap(); let mut map_lock = self.device_state_map.lock().unwrap();
*map_lock.get_mut(&dev_id).unwrap() = SwitchState::Unknown; *map_lock.get_mut(&dev_id).unwrap() = SwitchState::Unknown;
self.can_rx.recv(); self.can_rx.recv().unwrap();
self.can_rx.recv(); self.can_rx.recv().unwrap();
Ok(()) Ok(())
} else { } else {
Err(()) Err(())
} };
} }
pub fn update_states_helper(&mut self, dev_id: &DeviceId) -> Result<(), ()> { pub fn update_states_helper(&mut self, dev_id: &DeviceId) -> Result<(), ()> {
let switch_id: SwitchId = *dev_id as u16; let _switch_id: SwitchId = *dev_id as u16;
let dev_id_bytes = *dev_id as u8; let dev_id_bytes = *dev_id as u8;
let buf: &[u8] = &dev_id_bytes.to_be_bytes(); let buf: &[u8] = &dev_id_bytes.to_be_bytes();
self.can_tx.tx_socket(PackageId::DevicePowerStatusRequest, buf); self.can_tx.send(PackageModel::new(PackageId::DevicePowerStatusRequest, buf).unwrap()).unwrap();
match self.can_rx.recv_timeout(Duration::from_secs(10)) { match self.can_rx.recv_timeout(Duration::from_secs(10)) {
Ok(msg) => { Ok(msg) => {
if msg.package_id() == PackageId::DevicePowerStatusResponse && msg.data()[0] == dev_id_bytes{ if msg.package_id() == PackageId::DevicePowerStatusResponse
info!("received power status response"); && msg.data()[0] == dev_id_bytes
{
debug!("received power status response");
let mut map_lock = self.device_state_map.lock().unwrap(); let mut map_lock = self.device_state_map.lock().unwrap();
let mut state: SwitchState; let state: SwitchState;
match msg.data()[1] { match msg.data()[1] {
0 => { 0 => state = SwitchState::Off,
state = SwitchState::Off 1 => state = SwitchState::On,
}, 2 => state = SwitchState::Faulty,
1 => {
state = SwitchState::On
},
2 => {
state = SwitchState::Faulty
},
_ => { _ => {
return Err(()); return Err(());
} }
} }
*map_lock.get_mut(&dev_id).unwrap() = state; *map_lock.get_mut(&dev_id).unwrap() = state;
info!("{:?}", map_lock); debug!("{:?}", map_lock);
Ok(()) Ok(())
} else { } else {
Err(()) Err(())
} }
} }
Err(_) => { Err(_) => Err(()),
Err(())
} }
} }
}
pub fn update_all_states_helper(&mut self) -> Result<(), ()> { pub fn update_all_states_helper(&mut self) -> Result<(), ()> {
let mut map_lock = self.device_state_map.lock().unwrap(); let map_lock = self.device_state_map.lock().unwrap();
let mut device_list = vec::Vec::new(); let mut device_list = vec::Vec::new();
for key in map_lock.keys() { for key in map_lock.keys() {
device_list.push(key.clone()); device_list.push(key.clone());
@ -173,53 +183,50 @@ impl PCDU {
pub fn update_switch_states(&mut self, switch_id: SwitchId) -> Result<(), ()> { pub fn update_switch_states(&mut self, switch_id: SwitchId) -> Result<(), ()> {
return if let Ok(dev_id) = DeviceId::try_from(switch_id) { return if let Ok(dev_id) = DeviceId::try_from(switch_id) {
match dev_id { match dev_id {
DeviceId::All => { DeviceId::All => self.update_all_states_helper(),
self.update_all_states_helper() _ => self.update_states_helper(&dev_id),
}
_ => {
self.update_states_helper(&dev_id)
}
} }
} else { } else {
Err(()) Err(())
} };
} }
pub fn handle_power_requests(&mut self) -> Result<u16, ()>{ pub fn handle_power_requests(&mut self) -> Result<u16, ()> {
let mut i = 0; let mut i = 0;
while let Ok((switch_id, switch_state)) = self.switch_rx.recv() { while let Ok((switch_id, switch_state)) = self.switch_rx.recv() {
match switch_state { match switch_state {
SwitchState::Off => { SwitchState::Off => match self.send_power_off(switch_id) {
match self.send_power_off(switch_id) {
Ok(_) => { Ok(_) => {
i = i + 1; i = i + 1;
} }
Err(_) => { Err(_) => {
return Err(()); return Err(());
} }
} },
} SwitchState::On => match self.send_power_on(switch_id) {
SwitchState::On => {
match self.send_power_on(switch_id) {
Ok(_) => { Ok(_) => {
i = i + 1; i = i + 1;
} }
Err(_) => { Err(_) => {
return Err(()); return Err(());
} }
} },
}
_ => {} _ => {}
} }
self.update_switch_states(switch_id); self.update_switch_states(switch_id).unwrap();
} }
return Ok(i); return Ok(i);
} }
} }
pub fn core_power_task(switch_rx: Receiver<(SwitchId, SwitchState)>, can_tx: CanTxHandler, can_rx: Receiver<PackageModel>, device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>) { pub fn core_power_task(
switch_rx: Receiver<(SwitchId, SwitchState)>,
can_tx: Sender<PackageModel>,
can_rx: Receiver<PackageModel>,
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
) {
let mut pcdu = PCDU::new(switch_rx, can_tx, can_rx, device_state_map); let mut pcdu = PCDU::new(switch_rx, can_tx, can_rx, device_state_map);
loop{ loop {
pcdu.handle_power_requests().unwrap(); pcdu.handle_power_requests().unwrap();
} }
} }

View File

@ -14,8 +14,8 @@ use satrs_core::res_code::ResultU16;
use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper; use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper;
use satrs_core::tmtc::{AddressableId, PusServiceProvider}; use satrs_core::tmtc::{AddressableId, PusServiceProvider};
use satrs_core::{ use satrs_core::{
spacepackets::ecss::PusPacket, spacepackets::tc::PusTc, spacepackets::ecss::PusPacket, spacepackets::tc::PusTc, spacepackets::time::cds::TimeProvider,
spacepackets::time::cds::TimeProvider, spacepackets::time::TimeWriter, spacepackets::SpHeader, spacepackets::time::TimeWriter, spacepackets::SpHeader,
}; };
use std::cell::RefCell; use std::cell::RefCell;
@ -26,6 +26,7 @@ use satrs_core::pus::scheduling::PusScheduler;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use log::{debug};
pub struct PusReceiver { pub struct PusReceiver {
pub tm_helper: PusTmWithCdsShortHelper, pub tm_helper: PusTmWithCdsShortHelper,
@ -108,8 +109,8 @@ impl PusServiceProvider for PusReceiver {
impl PusReceiver { impl PusReceiver {
fn handle_test_service(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) { fn handle_test_service(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) {
if PusPacket::subservice(pus_tc) == 1 { if PusPacket::subservice(pus_tc) == 1 {
println!("Received PUS ping command TC[17,1]"); debug!("Received PUS ping command TC[17,1]");
println!("Sending ping reply PUS TM[17,2]"); debug!("Sending ping reply PUS TM[17,2]");
let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None); let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None);
let addr = self.tm_store.add_pus_tm(&ping_reply); let addr = self.tm_store.add_pus_tm(&ping_reply);
let start_token = self let start_token = self

View File

@ -16,7 +16,7 @@ use crate::pus::PusReceiver;
use crate::requests::RequestWithToken; use crate::requests::RequestWithToken;
use satrs_core::pool::{SharedPool, StoreAddr, StoreError}; use satrs_core::pool::{SharedPool, StoreAddr, StoreError};
use satrs_core::pus::event_man::EventRequestWithToken; use satrs_core::pus::event_man::EventRequestWithToken;
use satrs_core::pus::scheduling::PusScheduler; use satrs_core::pus::scheduling::{PusScheduler, TcInfo};
use satrs_core::pus::verification::StdVerifReporterWithSender; use satrs_core::pus::verification::StdVerifReporterWithSender;
use satrs_core::spacepackets::{ecss::PusPacket, tc::PusTc, tm::PusTm, SpHeader}; use satrs_core::spacepackets::{ecss::PusPacket, tc::PusTc, tm::PusTm, SpHeader};
use satrs_core::tmtc::{ use satrs_core::tmtc::{
@ -161,11 +161,11 @@ impl ReceivesCcsdsTc for PusTcSource {
} }
} }
pub fn core_tmtc_task(args: OtherArgs, mut tc_args: TcArgs, tm_args: TmArgs) { pub fn core_tmtc_task(args: OtherArgs, mut tc_args: TcArgs, tm_args: TmArgs) {
let mut scheduler = Rc::new(RefCell::new( let scheduler = Rc::new(RefCell::new(
PusScheduler::new_with_current_init_time(Duration::from_secs(5)).unwrap(), PusScheduler::new_with_current_init_time(Duration::from_secs(5)).unwrap(),
)); ));
let mut sched_clone = scheduler.clone(); let sched_clone = scheduler.clone();
let mut pus_receiver = PusReceiver::new( let mut pus_receiver = PusReceiver::new(
PUS_APID, PUS_APID,
tm_args.tm_sink_sender, tm_args.tm_sink_sender,
@ -196,7 +196,7 @@ pub fn core_tmtc_task(args: OtherArgs, mut tc_args: TcArgs, tm_args: TmArgs) {
let mut tc_buf: [u8; 4096] = [0; 4096]; let mut tc_buf: [u8; 4096] = [0; 4096];
loop { loop {
let mut tmtc_sched = scheduler.clone(); let tmtc_sched = scheduler.clone();
core_tmtc_loop( core_tmtc_loop(
&mut udp_tmtc_server, &mut udp_tmtc_server,
&mut tc_args, &mut tc_args,
@ -219,11 +219,15 @@ fn core_tmtc_loop(
pus_receiver: &mut PusReceiver, pus_receiver: &mut PusReceiver,
scheduler: Rc<RefCell<PusScheduler>>, scheduler: Rc<RefCell<PusScheduler>>,
) { ) {
let releaser = |enabled: bool, addr: &StoreAddr| -> bool { let releaser = |enabled: bool, info: &TcInfo| -> bool {
match tc_args.tc_source.tc_source.send(*addr) { if enabled {
Ok(_) => true, tc_args
Err(_) => false, .tc_source
.tc_source
.send(info.addr())
.expect("sending TC to TC source failed");
} }
true
}; };
let mut pool = tc_args let mut pool = tc_args
@ -235,15 +239,11 @@ fn core_tmtc_loop(
let mut scheduler = scheduler.borrow_mut(); let mut scheduler = scheduler.borrow_mut();
scheduler.update_time_from_now().unwrap(); scheduler.update_time_from_now().unwrap();
match scheduler.release_telecommands(releaser, pool.as_mut()) { if let Ok(released_tcs) = scheduler.release_telecommands(releaser, pool.as_mut()) {
Ok(released_tcs) => {
if released_tcs > 0 { if released_tcs > 0 {
println!("{} Tc(s) released from scheduler", released_tcs); println!("{released_tcs} TC(s) released from scheduler");
} }
} }
Err(_) => {}
}
//.expect("error releasing tc");
drop(pool); drop(pool);
drop(scheduler); drop(scheduler);