finished seq count, aocs handlers, housekeeper, maybe other stuff
This commit is contained in:
parent
8ceb2c7a79
commit
51471c0a2d
863835
output.log
863835
output.log
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,7 @@ from typing import Optional
|
||||
import datetime
|
||||
import json
|
||||
import pprint
|
||||
import struct
|
||||
|
||||
import tmtccmd
|
||||
from spacepackets.ecss import PusTelemetry, PusTelecommand, PusVerificator
|
||||
@ -17,7 +18,7 @@ from spacepackets.ecss.pus_1_verification import UnpackParams, Service1Tm
|
||||
from spacepackets.ccsds.time import CdsShortTimestamp
|
||||
|
||||
from tmtccmd import CcsdsTmtcBackend, TcHandlerBase, ProcedureParamsWrapper
|
||||
from tmtccmd.tc.pus_3_fsfw_hk import generate_one_hk_command, make_sid
|
||||
from tmtccmd.tc.pus_3_fsfw_hk import generate_one_hk_command, make_sid, create_enable_periodic_hk_command, create_disable_periodic_hk_command
|
||||
from tmtccmd.tc.pus_11_tc_sched import create_time_tagged_cmd
|
||||
from tmtccmd.core.base import BackendRequest
|
||||
from tmtccmd.pus import VerificationWrapper
|
||||
@ -56,7 +57,7 @@ from tmtccmd.util.tmtc_printer import FsfwTmTcPrinter
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
EXAMPLE_PUS_APID = 0x02
|
||||
EXAMPLE_PUS_APID = 0x50
|
||||
|
||||
|
||||
class SatRsConfigHook(HookBase):
|
||||
@ -96,6 +97,8 @@ class SatRsConfigHook(HookBase):
|
||||
)
|
||||
srv_3 = OpCodeEntry()
|
||||
srv_3.add(HkOpCodes.GENERATE_ONE_SHOT, "Generate AOCS one shot HK")
|
||||
srv_3.add(HkOpCodes.ENABLE_PERIODIC, "Enable Periodic AOCS HK")
|
||||
srv_3.add(HkOpCodes.DISABLE_PERIODIC, "Disable Periodic AOCS HK")
|
||||
defs.add_service(
|
||||
name=CoreServiceList.SERVICE_3,
|
||||
info="PUS Service 3 Housekeeping",
|
||||
@ -118,6 +121,15 @@ class SatRsConfigHook(HookBase):
|
||||
info="PUS Service 11 TC Scheduling",
|
||||
op_code_entry=srv_11,
|
||||
)
|
||||
|
||||
srv_200 = OpCodeEntry()
|
||||
srv_200.add("0", "AOCS Mode Idle")
|
||||
srv_200.add("1", "AOCS Mode On")
|
||||
defs.add_service(
|
||||
name = CoreServiceList.SERVICE_200,
|
||||
info="PUS Custom Service 200 Mode",
|
||||
op_code_entry=srv_200,
|
||||
)
|
||||
return defs
|
||||
|
||||
def perform_mode_operation(self, tmtc_backend: CcsdsTmtcBackend, mode: int):
|
||||
@ -178,9 +190,17 @@ class PusHandler(SpecificApidHandlerBase):
|
||||
if pus_tm.subservice == 25:
|
||||
if len(pus_tm.source_data) < 8:
|
||||
raise ValueError("No addressable ID in HK packet")
|
||||
json_str = str(pus_tm.source_data[8:].decode('utf8'))
|
||||
json_object = json.loads(json_str)
|
||||
pprint.pprint(json_object)
|
||||
#json_str = str(pus_tm.source_data[8:].decode('utf8'))
|
||||
#json_object = json.loads(json_str)
|
||||
#pprint.pprint(json_object)
|
||||
print(pus_tm.tm_data.hex())
|
||||
i = 8
|
||||
print(struct.unpack('d', pus_tm.tm_data[8:16]))
|
||||
|
||||
while i < len(pus_tm.tm_data):
|
||||
print(pus_tm.tm_data[i:i+8].hex())
|
||||
print(struct.unpack('d', pus_tm.tm_data[i:i+8]))
|
||||
i += 8
|
||||
dedicated_handler = True
|
||||
if service == 5:
|
||||
tm_packet = Service5Tm.unpack(packet, time_reader=CdsShortTimestamp.empty())
|
||||
@ -242,12 +262,19 @@ class AcsHkIds(enum.IntEnum):
|
||||
|
||||
class HkOpCodes:
|
||||
GENERATE_ONE_SHOT = ["0", "oneshot"]
|
||||
ENABLE_PERIODIC = ["1", "enable periodic"]
|
||||
DISABLE_PERIODIC = ["2", "disable periodic"]
|
||||
|
||||
|
||||
|
||||
def make_target_id(target_id: int) -> bytes:
|
||||
byte_string = bytearray(struct.pack("!I", target_id))
|
||||
return byte_string
|
||||
|
||||
def make_mode_submode(mode: int, submode: int) -> bytes:
|
||||
byte_string = bytearray(struct.pack("!I", mode))
|
||||
byte_string.extend(struct.pack("!I", submode))
|
||||
return byte_string
|
||||
|
||||
class TcHandler(TcHandlerBase):
|
||||
def __init__(
|
||||
@ -294,6 +321,15 @@ class TcHandler(TcHandlerBase):
|
||||
def_proc = helper.to_def_procedure()
|
||||
service = def_proc.service
|
||||
op_code = def_proc.op_code
|
||||
if service == CoreServiceList.SERVICE_200:
|
||||
q.add_log_cmd("Sending PUS Mode Request telecommand")
|
||||
if op_code == "0":
|
||||
tc = PusTelecommand(service=200, subservice=1, app_data=make_mode_submode(0,0), apid=0x50)
|
||||
return q.add_pus_tc(tc)
|
||||
if op_code == "1":
|
||||
tc = PusTelecommand(service=200, subservice=1, app_data=make_mode_submode(1,0), apid=0x50)
|
||||
return q.add_pus_tc(tc)
|
||||
|
||||
if (
|
||||
service == CoreServiceList.SERVICE_17
|
||||
or service == CoreServiceList.SERVICE_17_ALT
|
||||
@ -346,6 +382,16 @@ class TcHandler(TcHandlerBase):
|
||||
make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET)
|
||||
)
|
||||
)
|
||||
if op_code in HkOpCodes.ENABLE_PERIODIC:
|
||||
q.add_log_cmd("Sending periodic HK request")
|
||||
tc = create_enable_periodic_hk_command(False, make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET))
|
||||
q.add_log_cmd(tc)
|
||||
q.add_pus_tc(tc)
|
||||
if op_code in HkOpCodes.DISABLE_PERIODIC:
|
||||
q.add_log_cmd("Sending periodic HK request")
|
||||
tc = create_disable_periodic_hk_command(False, make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET))
|
||||
q.add_log_cmd(tc)
|
||||
q.add_pus_tc(tc)
|
||||
pass
|
||||
|
||||
|
||||
|
821
src/aocs.rs
821
src/aocs.rs
@ -1,32 +1,36 @@
|
||||
use crate::action::ActionRequest;
|
||||
use crate::aocs::AOCSSensorMode::{Idle, SendingData};
|
||||
use crate::can_ids::PackageId::AOCSDataStarTracker1;
|
||||
use crate::can_ids::{DeviceId, PackageId, PackageModel};
|
||||
use crate::hk::{AOCSSensorData, AocsHousekeeper};
|
||||
use crate::helpers::{ModeHelper, VerifHelper};
|
||||
use crate::hk::{AocsDataMap, AocsDataType, AocsHousekeeper, CSS_VOLTAGE_1, CSS_VOLTAGE_2, CSS_VOLTAGE_3, CSS_VOLTAGE_4, CSS_VOLTAGE_5, CSS_VOLTAGE_6, MGM_VOLTAGE_1, MGM_VOLTAGE_2, MGM_VOLTAGE_3, STR_QUATERNION_1, STR_QUATERNION_2, STR_QUATERNION_3, STR_QUATERNION_4};
|
||||
use crate::power_handler::{DeviceState, PowerSwitcher};
|
||||
use crate::requests::{Request, RequestWithToken};
|
||||
use crate::tmtc::TmStore;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use num_derive::ToPrimitive;
|
||||
use satrs_core::hk::HkRequest;
|
||||
use satrs_core::mode::ModeRequest;
|
||||
use satrs_core::mode::{ModeAndSubmode, ModeRequest};
|
||||
use satrs_core::pool::StoreAddr;
|
||||
use satrs_core::power::SwitchId;
|
||||
use satrs_core::power::{PowerSwitcherCommandSender, SwitchId};
|
||||
use satrs_core::pus::verification::{
|
||||
TcStateAccepted, TcStateNone, VerificationReporterWithSender, VerificationToken,
|
||||
};
|
||||
use satrs_core::pus::MpscPusInStoreSendError;
|
||||
use satrs_core::seq_count::SeqCountProviderSyncClonable;
|
||||
use satrs_core::spacepackets::time::cds::TimeProvider;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::u32;
|
||||
|
||||
#[derive(ToPrimitive)]
|
||||
#[derive(ToPrimitive, PartialEq, Copy, Clone)]
|
||||
pub enum AOCSSensorMode {
|
||||
Idle = 0,
|
||||
SendingData = 1,
|
||||
}
|
||||
|
||||
pub trait AOCSSensorHandler {
|
||||
pub trait AocsSensorHandler {
|
||||
type Error;
|
||||
|
||||
fn get_package_id(&mut self) -> Result<PackageId, Self::Error>;
|
||||
@ -48,138 +52,21 @@ pub trait AOCSSensorHandler {
|
||||
}
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct CSSData {
|
||||
voltage_1: f64,
|
||||
voltage_2: f64,
|
||||
voltage_3: f64,
|
||||
voltage_4: f64,
|
||||
voltage_5: f64,
|
||||
voltage_6: f64,
|
||||
}
|
||||
|
||||
impl CSSData {
|
||||
pub fn from_floats(
|
||||
voltage_1: f64,
|
||||
voltage_2: f64,
|
||||
voltage_3: f64,
|
||||
voltage_4: f64,
|
||||
voltage_5: f64,
|
||||
voltage_6: f64,
|
||||
) -> CSSData {
|
||||
CSSData {
|
||||
voltage_1,
|
||||
voltage_2,
|
||||
voltage_3,
|
||||
voltage_4,
|
||||
voltage_5,
|
||||
voltage_6,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> CSSData {
|
||||
CSSData {
|
||||
voltage_1: 0.0,
|
||||
voltage_2: 0.0,
|
||||
voltage_3: 0.0,
|
||||
voltage_4: 0.0,
|
||||
voltage_5: 0.0,
|
||||
voltage_6: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
voltage_1: f64,
|
||||
voltage_2: f64,
|
||||
voltage_3: f64,
|
||||
voltage_4: f64,
|
||||
voltage_5: f64,
|
||||
voltage_6: f64,
|
||||
) {
|
||||
self.voltage_1 = voltage_1;
|
||||
self.voltage_2 = voltage_2;
|
||||
self.voltage_3 = voltage_3;
|
||||
self.voltage_4 = voltage_4;
|
||||
self.voltage_5 = voltage_5;
|
||||
self.voltage_6 = voltage_6;
|
||||
}
|
||||
|
||||
pub fn to_array(&self) -> [f64; 6] {
|
||||
[
|
||||
self.voltage_1,
|
||||
self.voltage_2,
|
||||
self.voltage_3,
|
||||
self.voltage_4,
|
||||
self.voltage_5,
|
||||
self.voltage_6,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn to_tuple(&self) -> (f64, f64, f64, f64, f64, f64) {
|
||||
(
|
||||
self.voltage_1,
|
||||
self.voltage_2,
|
||||
self.voltage_3,
|
||||
self.voltage_4,
|
||||
self.voltage_5,
|
||||
self.voltage_6,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CSSHandler {
|
||||
power_switcher: PowerSwitcher,
|
||||
device_id: DeviceId,
|
||||
switch_id: SwitchId,
|
||||
device_state: DeviceState,
|
||||
device_mode: AOCSSensorMode,
|
||||
css_data: Arc<Mutex<CSSData>>,
|
||||
mode: AOCSSensorMode,
|
||||
aocs_data: Arc<Mutex<AocsDataMap>>,
|
||||
can_tx: Sender<PackageModel>,
|
||||
can_rx: Receiver<PackageModel>,
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
}
|
||||
|
||||
impl AOCSSensorHandler for CSSHandler {
|
||||
impl AocsSensorHandler for CSSHandler {
|
||||
type Error = ();
|
||||
|
||||
fn get_package_id(&mut self) -> Result<PackageId, Self::Error> {
|
||||
@ -198,73 +85,164 @@ impl CSSHandler {
|
||||
pub fn new(
|
||||
power_switcher: PowerSwitcher,
|
||||
device_id: DeviceId,
|
||||
switch_id: SwitchId,
|
||||
device_state: DeviceState,
|
||||
device_mode: AOCSSensorMode,
|
||||
css_data: Arc<Mutex<CSSData>>,
|
||||
aocs_data: Arc<Mutex<AocsDataMap>>,
|
||||
can_tx: Sender<PackageModel>,
|
||||
can_rx: Receiver<PackageModel>,
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
) -> CSSHandler {
|
||||
CSSHandler {
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
) -> Self {
|
||||
let switch_id = device_id as u16;
|
||||
Self {
|
||||
power_switcher,
|
||||
device_id,
|
||||
switch_id,
|
||||
device_state,
|
||||
device_mode,
|
||||
css_data: Arc::new(Mutex::new(CSSData::default())),
|
||||
mode: Idle,
|
||||
aocs_data,
|
||||
can_tx,
|
||||
can_rx,
|
||||
request_rx,
|
||||
verif_helper,
|
||||
mode_helper,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_data_ref(&mut self) -> Arc<Mutex<CSSData>> {
|
||||
self.css_data.clone()
|
||||
pub fn periodic_op(&mut self) {
|
||||
self.handle_requests();
|
||||
self.read_can();
|
||||
}
|
||||
|
||||
pub fn css_core_task(&mut self) {
|
||||
self.handle_request_messages();
|
||||
}
|
||||
fn handle_requests(&mut self) {
|
||||
if let Ok(req) = self.request_rx.try_recv() {
|
||||
let (req, start_token) = self
|
||||
.verif_helper
|
||||
.start_and_unwrap(req)
|
||||
.expect("error sending start of execution");
|
||||
match req {
|
||||
Request::HkRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
Request::ModeRequest(req) => match req {
|
||||
ModeRequest::SetMode(mode_submode) => {
|
||||
if let Some(aocs_mode) = mode_submode_to_aocs_mode(mode_submode) {
|
||||
self.mode = aocs_mode;
|
||||
}
|
||||
|
||||
fn handle_request_messages(&mut self) {
|
||||
let request = self.request_rx.try_recv().unwrap();
|
||||
let token = request.1.unwrap();
|
||||
match request.0 {
|
||||
Request::HkRequest(_) => {}
|
||||
Request::ModeRequest(request) => {
|
||||
self.handle_mode_request(request, token);
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
ModeRequest::ReadMode => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
ModeRequest::AnnounceMode => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
ModeRequest::AnnounceModeRecursive => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
},
|
||||
Request::ActionRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
Request::ActionRequest(request) => self.handle_action_request(request, token),
|
||||
}
|
||||
}
|
||||
fn set_mode_reading(&mut self) {
|
||||
if self.mode == SendingData {
|
||||
return;
|
||||
}
|
||||
|
||||
fn handle_mode_request(
|
||||
&mut self,
|
||||
request: ModeRequest,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
) {
|
||||
match request {
|
||||
ModeRequest::SetMode(mode) => match mode.mode() {
|
||||
0 => {}
|
||||
// TODO: currently unrecoverable, should probably be changed
|
||||
self.power_switcher
|
||||
.send_switch_on_cmd(self.switch_id)
|
||||
.expect("error sending switch on cmd");
|
||||
self.enable_sensor_data_generation()
|
||||
.expect("error enabling sensor data generation");
|
||||
self.mode = SendingData;
|
||||
}
|
||||
|
||||
fn set_mode_idle(&mut self) {
|
||||
if self.mode == Idle {
|
||||
return;
|
||||
}
|
||||
|
||||
self.disable_sensor_data_generation()
|
||||
.expect("error disabling sensor data generation");
|
||||
self.power_switcher
|
||||
.send_switch_off_cmd(self.switch_id)
|
||||
.expect("error sending switch off cmd");
|
||||
self.mode = Idle;
|
||||
}
|
||||
|
||||
fn read_can(&mut self) {
|
||||
if let Ok(package) = self.can_rx.try_recv() {
|
||||
let mut map = self.aocs_data.lock().expect("error locking data map");
|
||||
let float_data = self.decode_sensor_data(package.data());
|
||||
match package.package_id() {
|
||||
PackageId::AOCSDataSunSensor1 => {
|
||||
map.update_value(CSS_VOLTAGE_1, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataSunSensor2 => {
|
||||
map.update_value(CSS_VOLTAGE_2, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataSunSensor3 => {
|
||||
map.update_value(CSS_VOLTAGE_3, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataSunSensor4 => {
|
||||
map.update_value(CSS_VOLTAGE_4, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataSunSensor5 => {
|
||||
map.update_value(CSS_VOLTAGE_5, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataSunSensor6 => {
|
||||
map.update_value(CSS_VOLTAGE_6, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
ModeRequest::ReadMode => {}
|
||||
ModeRequest::AnnounceMode => {}
|
||||
ModeRequest::AnnounceModeRecursive => {}
|
||||
}
|
||||
drop(map);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_action_request(
|
||||
&mut self,
|
||||
request: ActionRequest,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
) {
|
||||
match request {
|
||||
ActionRequest::ImageRequest(target_id) => {}
|
||||
ActionRequest::OrientationRequest(_) => {}
|
||||
ActionRequest::PointingRequest(_) => {}
|
||||
}
|
||||
fn decode_sensor_data(&self, buf: &[u8]) -> f64 {
|
||||
LittleEndian::read_f64(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,14 +251,16 @@ pub struct MGMHandler {
|
||||
device_id: DeviceId,
|
||||
switch_id: SwitchId,
|
||||
device_state: DeviceState,
|
||||
mode: AOCSSensorMode,
|
||||
aocs_data: Arc<Mutex<AocsDataMap>>,
|
||||
can_tx: Sender<PackageModel>,
|
||||
can_rx: Receiver<PackageModel>,
|
||||
mode: AOCSSensorMode,
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
mgm_data: Arc<Mutex<MGMData>>,
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
}
|
||||
|
||||
impl AOCSSensorHandler for MGMHandler {
|
||||
impl AocsSensorHandler for MGMHandler {
|
||||
type Error = ();
|
||||
|
||||
fn get_package_id(&mut self) -> Result<PackageId, Self::Error> {
|
||||
@ -299,113 +279,478 @@ impl MGMHandler {
|
||||
pub fn new(
|
||||
power_switcher: PowerSwitcher,
|
||||
device_id: DeviceId,
|
||||
device_state: DeviceState,
|
||||
aocs_data: Arc<Mutex<AocsDataMap>>,
|
||||
can_tx: Sender<PackageModel>,
|
||||
can_rx: Receiver<PackageModel>,
|
||||
action_rx: Receiver<RequestWithToken>,
|
||||
) -> MGMHandler {
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
) -> Self {
|
||||
let switch_id = device_id as u16;
|
||||
MGMHandler {
|
||||
Self {
|
||||
power_switcher,
|
||||
device_id,
|
||||
switch_id,
|
||||
device_state: DeviceState::Off,
|
||||
device_state,
|
||||
mode: Idle,
|
||||
aocs_data,
|
||||
can_tx,
|
||||
can_rx,
|
||||
mode: AOCSSensorMode::Idle,
|
||||
request_rx: action_rx,
|
||||
mgm_data: Arc::new(Mutex::new(MGMData::new())),
|
||||
request_rx,
|
||||
verif_helper,
|
||||
mode_helper,
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
self.read_can();
|
||||
}
|
||||
|
||||
pub fn update_mode(&mut self) {}
|
||||
fn handle_requests(&mut self) {
|
||||
if let Ok(req) = self.request_rx.try_recv() {
|
||||
let (req, start_token) = self
|
||||
.verif_helper
|
||||
.start_and_unwrap(req)
|
||||
.expect("error sending start of execution");
|
||||
match req {
|
||||
Request::HkRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
Request::ModeRequest(req) => match req {
|
||||
ModeRequest::SetMode(mode_submode) => {
|
||||
if let Some(aocs_mode) = mode_submode_to_aocs_mode(mode_submode) {
|
||||
self.mode = aocs_mode;
|
||||
}
|
||||
|
||||
pub fn handle_requests(&mut self) {
|
||||
if self.device_state == DeviceState::On {
|
||||
if let Ok(request) = self.request_rx.try_recv() {
|
||||
match request.0 {
|
||||
Request::HkRequest(hk_req) => {
|
||||
//self.handle_hk_request(hk_req);
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
Request::ActionRequest(_action_request) => {
|
||||
//self.handle_action_request(action_request);
|
||||
ModeRequest::ReadMode => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
Request::ModeRequest(_mode_request) => {
|
||||
//self.handle_mode_request(mode_request);
|
||||
ModeRequest::AnnounceMode => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
ModeRequest::AnnounceModeRecursive => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
},
|
||||
Request::ActionRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_mode_request(&mut self, mode_request: ModeRequest) {
|
||||
match mode_request {
|
||||
ModeRequest::SetMode(_) => {}
|
||||
ModeRequest::ReadMode => {}
|
||||
ModeRequest::AnnounceMode => {}
|
||||
ModeRequest::AnnounceModeRecursive => {}
|
||||
fn set_mode_reading(&mut self) {
|
||||
if self.mode == SendingData {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: currently unrecoverable, should probably be changed
|
||||
self.power_switcher
|
||||
.send_switch_on_cmd(self.switch_id)
|
||||
.expect("error sending switch on cmd");
|
||||
self.enable_sensor_data_generation()
|
||||
.expect("error enabling sensor data generation");
|
||||
self.mode = SendingData;
|
||||
}
|
||||
|
||||
/*
|
||||
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(_, _) => {}
|
||||
fn set_mode_idle(&mut self) {
|
||||
if self.mode == Idle {
|
||||
return;
|
||||
}
|
||||
|
||||
self.disable_sensor_data_generation()
|
||||
.expect("error disabling sensor data generation");
|
||||
self.power_switcher
|
||||
.send_switch_off_cmd(self.switch_id)
|
||||
.expect("error sending switch off cmd");
|
||||
self.mode = Idle;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
pub fn read_sensor_data(&mut self) {
|
||||
fn read_can(&mut self) {
|
||||
if let Ok(package) = self.can_rx.try_recv() {
|
||||
let mut map = self.aocs_data.lock().expect("error locking data map");
|
||||
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,
|
||||
_ => {}
|
||||
match package.package_id() {
|
||||
PackageId::AOCSDataStarTracker1 => {
|
||||
map.update_value(STR_QUATERNION_1, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataStarTracker2 => {
|
||||
map.update_value(STR_QUATERNION_2, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataStarTracker3 => {
|
||||
map.update_value(STR_QUATERNION_3, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataStarTracker4 => {
|
||||
map.update_value(STR_QUATERNION_4, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
drop(map);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_sensor_data(&mut self, buf: &[u8]) -> f64 {
|
||||
fn decode_sensor_data(&self, buf: &[u8]) -> f64 {
|
||||
LittleEndian::read_f64(&buf)
|
||||
}
|
||||
//pub fn handle_action_request(&mut self, action_request: ActionRequest) {}
|
||||
}
|
||||
|
||||
pub struct AOCSController {
|
||||
aocs_housekeeper: AocsHousekeeper,
|
||||
mgm_handler: MGMHandler,
|
||||
pub struct STRHandler {
|
||||
power_switcher: PowerSwitcher,
|
||||
device_id: DeviceId,
|
||||
switch_id: SwitchId,
|
||||
device_state: DeviceState,
|
||||
mode: AOCSSensorMode,
|
||||
aocs_data: Arc<Mutex<AocsDataMap>>,
|
||||
can_tx: Sender<PackageModel>,
|
||||
can_rx: Receiver<PackageModel>,
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
}
|
||||
|
||||
impl AocsSensorHandler for STRHandler {
|
||||
type Error = ();
|
||||
|
||||
fn get_package_id(&mut self) -> Result<PackageId, Self::Error> {
|
||||
Ok(PackageId::AOCSDataRequestStarTracker)
|
||||
}
|
||||
|
||||
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 STRHandler {
|
||||
pub fn new(
|
||||
power_switcher: PowerSwitcher,
|
||||
device_id: DeviceId,
|
||||
device_state: DeviceState,
|
||||
aocs_data: Arc<Mutex<AocsDataMap>>,
|
||||
can_tx: Sender<PackageModel>,
|
||||
can_rx: Receiver<PackageModel>,
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
) -> Self {
|
||||
let switch_id = device_id as u16;
|
||||
Self {
|
||||
power_switcher,
|
||||
device_id,
|
||||
switch_id,
|
||||
device_state,
|
||||
mode: Idle,
|
||||
aocs_data,
|
||||
can_tx,
|
||||
can_rx,
|
||||
request_rx,
|
||||
verif_helper,
|
||||
mode_helper,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn periodic_op(&mut self) {
|
||||
self.handle_requests();
|
||||
self.read_can();
|
||||
}
|
||||
|
||||
fn handle_requests(&mut self) {
|
||||
if let Ok(req) = self.request_rx.try_recv() {
|
||||
let (req, start_token) = self
|
||||
.verif_helper
|
||||
.start_and_unwrap(req)
|
||||
.expect("error sending start of execution");
|
||||
match req {
|
||||
Request::HkRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
Request::ModeRequest(req) => match req {
|
||||
ModeRequest::SetMode(mode_submode) => {
|
||||
if let Some(aocs_mode) = mode_submode_to_aocs_mode(mode_submode) {
|
||||
self.mode = aocs_mode;
|
||||
}
|
||||
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
ModeRequest::ReadMode => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
ModeRequest::AnnounceMode => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
ModeRequest::AnnounceModeRecursive => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
},
|
||||
Request::ActionRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_mode_reading(&mut self) {
|
||||
if self.mode == SendingData {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: currently unrecoverable, should probably be changed
|
||||
self.power_switcher
|
||||
.send_switch_on_cmd(self.switch_id)
|
||||
.expect("error sending switch on cmd");
|
||||
self.enable_sensor_data_generation()
|
||||
.expect("error enabling sensor data generation");
|
||||
self.mode = SendingData;
|
||||
}
|
||||
|
||||
fn set_mode_idle(&mut self) {
|
||||
if self.mode == Idle {
|
||||
return;
|
||||
}
|
||||
|
||||
self.disable_sensor_data_generation()
|
||||
.expect("error disabling sensor data generation");
|
||||
self.power_switcher
|
||||
.send_switch_off_cmd(self.switch_id)
|
||||
.expect("error sending switch off cmd");
|
||||
self.mode = Idle;
|
||||
}
|
||||
|
||||
fn read_can(&mut self) {
|
||||
if let Ok(package) = self.can_rx.try_recv() {
|
||||
let mut map = self.aocs_data.lock().expect("error locking data map");
|
||||
let float_data = self.decode_sensor_data(package.data());
|
||||
match package.package_id() {
|
||||
PackageId::AOCSDataMGM1 => {
|
||||
map.update_value(MGM_VOLTAGE_1, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataMGM2 => {
|
||||
map.update_value(MGM_VOLTAGE_2, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
PackageId::AOCSDataMGM2 => {
|
||||
map.update_value(MGM_VOLTAGE_3, AocsDataType::float_value(float_data))
|
||||
.expect("error updating value");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
drop(map);
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_sensor_data(&self, buf: &[u8]) -> f64 {
|
||||
LittleEndian::read_f64(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AocsController {
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
hk_request_tx: Sender<RequestWithToken>,
|
||||
mgm_request_tx: Sender<RequestWithToken>,
|
||||
css_request_tx: Sender<RequestWithToken>,
|
||||
str_request_tx: Sender<RequestWithToken>,
|
||||
seq_count_provider: SeqCountProviderSyncClonable,
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
mode: AOCSSensorMode,
|
||||
}
|
||||
|
||||
impl AocsController {
|
||||
pub fn new(
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
mgm_request_tx: Sender<RequestWithToken>,
|
||||
css_request_tx: Sender<RequestWithToken>,
|
||||
str_request_tx: Sender<RequestWithToken>,
|
||||
seq_count_provider: SeqCountProviderSyncClonable,
|
||||
verif_helper: VerifHelper,
|
||||
mode_helper: ModeHelper,
|
||||
) -> Self {
|
||||
Self {
|
||||
request_rx,
|
||||
mgm_request_tx,
|
||||
css_request_tx,
|
||||
str_request_tx,
|
||||
seq_count_provider,
|
||||
verif_helper,
|
||||
mode_helper,
|
||||
mode: Idle,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn periodic_op(&mut self) {
|
||||
self.handle_requests();
|
||||
}
|
||||
|
||||
fn handle_requests(&mut self) {
|
||||
if let Ok(req) = self.request_rx.try_recv() {
|
||||
let (req, start_token) = self
|
||||
.verif_helper
|
||||
.start_and_unwrap(req)
|
||||
.expect("error sending start of execution");
|
||||
match req {
|
||||
Request::HkRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
Request::ModeRequest(req) => match req {
|
||||
ModeRequest::SetMode(mode_submode) => {
|
||||
if let Some(aocs_mode) = mode_submode_to_aocs_mode(mode_submode) {
|
||||
self.mode = aocs_mode;
|
||||
}
|
||||
self.mgm_request_tx
|
||||
.send(RequestWithToken(Request::ModeRequest(req), None))
|
||||
.expect("error sending to mgm");
|
||||
self.css_request_tx
|
||||
.send(RequestWithToken(Request::ModeRequest(req), None))
|
||||
.expect("error sending to css");
|
||||
self.str_request_tx
|
||||
.send(RequestWithToken(Request::ModeRequest(req), None))
|
||||
.expect("error sending to str");
|
||||
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
ModeRequest::ReadMode => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion success");
|
||||
}
|
||||
}
|
||||
ModeRequest::AnnounceMode => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
ModeRequest::AnnounceModeRecursive => {
|
||||
self.mode_helper
|
||||
.make_and_send_mode_reply(aocs_mode_to_mode_submode(self.mode))
|
||||
.expect("error sending mode reply");
|
||||
|
||||
self.mgm_request_tx
|
||||
.send(RequestWithToken(Request::ModeRequest(req), None))
|
||||
.expect("error sending mode request to mgm handler");
|
||||
self.css_request_tx
|
||||
.send(RequestWithToken(Request::ModeRequest(req), None))
|
||||
.expect("error sending mode request to css handler");
|
||||
self.str_request_tx
|
||||
.send(RequestWithToken(Request::ModeRequest(req), None))
|
||||
.expect("error sending mode request to str handler");
|
||||
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
},
|
||||
Request::ActionRequest(_) => {
|
||||
if let Some(token) = start_token {
|
||||
self.verif_helper
|
||||
.completion_failure(token)
|
||||
.expect("error sending completion failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn aocs_mode_to_mode_submode(sensor_mode: AOCSSensorMode) -> ModeAndSubmode {
|
||||
match sensor_mode {
|
||||
Idle => ModeAndSubmode::new(0, 0),
|
||||
SendingData => ModeAndSubmode::new(1, 0),
|
||||
}
|
||||
}
|
||||
|
||||
fn mode_submode_to_aocs_mode(mode_submode: ModeAndSubmode) -> Option<AOCSSensorMode> {
|
||||
match mode_submode.mode() {
|
||||
0 => Some(Idle),
|
||||
1 => Some(SendingData),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn core_aocs_loop() {}
|
||||
|
157
src/helpers.rs
Normal file
157
src/helpers.rs
Normal file
@ -0,0 +1,157 @@
|
||||
use crate::requests::{Request, RequestWithToken};
|
||||
use crate::tmtc::TmStore;
|
||||
use eurosim_obsw::tmtc_err;
|
||||
use satrs_core::mode::ModeAndSubmode;
|
||||
use satrs_core::pool::StoreAddr;
|
||||
use satrs_core::pus::mode::Subservice::TmModeReply;
|
||||
use satrs_core::pus::verification::{
|
||||
FailParams, TcStateAccepted, TcStateStarted, VerificationReporterWithSender, VerificationToken,
|
||||
};
|
||||
use satrs_core::pus::MpscPusInStoreSendError;
|
||||
use satrs_core::seq_count::{SeqCountProviderSyncClonable, SequenceCountProviderCore};
|
||||
use satrs_core::spacepackets::tc::PusTc;
|
||||
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 std::sync::mpsc::Sender;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VerifHelper {
|
||||
verif_reporter: VerificationReporterWithSender<MpscPusInStoreSendError>,
|
||||
time_stamp_buf: [u8; 7],
|
||||
}
|
||||
|
||||
impl VerifHelper {
|
||||
pub fn new(verif_reporter: VerificationReporterWithSender<MpscPusInStoreSendError>) -> Self {
|
||||
Self {
|
||||
verif_reporter,
|
||||
time_stamp_buf: [0; 7],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_and_unwrap(
|
||||
&mut self,
|
||||
request_with_token: RequestWithToken,
|
||||
) -> Result<(Request, Option<VerificationToken<TcStateStarted>>), ()> {
|
||||
match request_with_token.1 {
|
||||
None => Ok((request_with_token.0, None)),
|
||||
Some(token) => {
|
||||
self.update_time_stamp();
|
||||
if let Ok(start_token) = self //implement this for verification
|
||||
.verif_reporter
|
||||
.start_success(token, Some(&self.time_stamp_buf))
|
||||
{
|
||||
return Ok((request_with_token.0, Some(start_token)));
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_failure(&mut self, request_with_token: RequestWithToken) -> Result<(), ()> {
|
||||
if let Some(token) = request_with_token.1 {
|
||||
self.update_time_stamp();
|
||||
if let Ok(()) = self.verif_reporter.start_failure(
|
||||
token,
|
||||
FailParams::new(
|
||||
Some(&mut self.time_stamp_buf),
|
||||
&tmtc_err::INVALID_PUS_SUBSERVICE,
|
||||
None,
|
||||
),
|
||||
) {
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn completion(&mut self, start_token: VerificationToken<TcStateStarted>) -> Result<(), ()> {
|
||||
self.update_time_stamp();
|
||||
if let Ok(()) = self
|
||||
.verif_reporter
|
||||
.completion_success(start_token, Some(&self.time_stamp_buf))
|
||||
{
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn completion_failure(
|
||||
&mut self,
|
||||
start_token: VerificationToken<TcStateStarted>,
|
||||
) -> Result<(), ()> {
|
||||
self.update_time_stamp();
|
||||
if let Ok(()) = self.verif_reporter.completion_failure(
|
||||
start_token,
|
||||
FailParams::new(
|
||||
Some(&mut self.time_stamp_buf),
|
||||
&tmtc_err::INVALID_PUS_SUBSERVICE,
|
||||
None,
|
||||
),
|
||||
) {
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
fn update_time_stamp(&mut self) {
|
||||
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
|
||||
cds_stamp.write_to_bytes(&mut self.time_stamp_buf).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModeHelper {
|
||||
apid: u16,
|
||||
seq_count_provider: SeqCountProviderSyncClonable,
|
||||
tm_store: TmStore,
|
||||
tm_funnel_tx: Sender<StoreAddr>,
|
||||
buf: [u8; 6],
|
||||
time_stamp_buf: [u8; 7],
|
||||
}
|
||||
|
||||
impl ModeHelper {
|
||||
pub fn new(
|
||||
apid: u16,
|
||||
seq_count_provider: SeqCountProviderSyncClonable,
|
||||
tm_store: TmStore,
|
||||
tm_funnel_tx: Sender<StoreAddr>,
|
||||
) -> Self {
|
||||
Self {
|
||||
apid,
|
||||
seq_count_provider,
|
||||
tm_store,
|
||||
tm_funnel_tx,
|
||||
buf: [0; 6],
|
||||
time_stamp_buf: [0; 7],
|
||||
}
|
||||
}
|
||||
|
||||
fn update_time_stamp(&mut self) {
|
||||
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
|
||||
cds_stamp.write_to_bytes(&mut self.time_stamp_buf).unwrap();
|
||||
}
|
||||
|
||||
pub fn make_and_send_mode_reply(
|
||||
&mut self,
|
||||
mode_submode: ModeAndSubmode,
|
||||
) -> Result<(), std::sync::mpsc::SendError<StoreAddr>> {
|
||||
self.update_time_stamp();
|
||||
let mut sp_header =
|
||||
SpHeader::tm_unseg(self.apid, self.seq_count_provider.get_and_increment(), 0).unwrap();
|
||||
self.buf[0..4].copy_from_slice(&mode_submode.mode().to_be_bytes());
|
||||
self.buf[4..6].copy_from_slice(&mode_submode.submode().to_be_bytes());
|
||||
let mut len = 6;
|
||||
let data = self.buf[0..len].to_vec();
|
||||
let tm_sec_header =
|
||||
PusTmSecondaryHeader::new_simple(200, TmModeReply as u8, &self.time_stamp_buf);
|
||||
let tm = PusTm::new(&mut sp_header, tm_sec_header, Some(&self.buf[0..len]), true);
|
||||
let addr = self.tm_store.add_pus_tm(&tm);
|
||||
self.tm_funnel_tx.send(addr)
|
||||
}
|
||||
}
|
185
src/hk.rs
185
src/hk.rs
@ -1,13 +1,14 @@
|
||||
use std::collections::HashMap;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::aocs::{CSSData, MGMData};
|
||||
use crate::hk::AocsDataType::float_value;
|
||||
use crate::requests::Request;
|
||||
use crate::requests::RequestWithToken;
|
||||
use crate::tmtc::{TmStore, AOCS_HK_APID};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use byteorder::{BigEndian, ByteOrder, LittleEndian};
|
||||
use chrono::Duration;
|
||||
use eurosim_obsw::hk_err;
|
||||
use log::debug;
|
||||
use num_enum::FromPrimitive;
|
||||
use satrs_core::hk::{HkRequest, UniqueId};
|
||||
use satrs_core::pool::StoreAddr;
|
||||
@ -15,12 +16,13 @@ use satrs_core::pus::hk::Subservice;
|
||||
use satrs_core::pus::verification::{FailParams, VerificationReporterWithSender};
|
||||
use satrs_core::pus::MpscPusInStoreSendError;
|
||||
use satrs_core::seq_count::{SeqCountProviderSyncClonable, SequenceCountProviderCore};
|
||||
use satrs_core::spacepackets::time::cds::TimeProvider;
|
||||
use satrs_core::spacepackets::time::TimeWriter;
|
||||
use satrs_core::spacepackets::time::cds::{CdsCommon, TimeProvider};
|
||||
use satrs_core::spacepackets::time::{CcsdsTimeProvider, TimeWriter};
|
||||
use satrs_core::spacepackets::tm::{PusTm, PusTmSecondaryHeader};
|
||||
use satrs_core::spacepackets::SpHeader;
|
||||
use satrs_core::tmtc::AddressableId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::from_slice;
|
||||
use std::ops::Deref;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -42,6 +44,8 @@ pub const STR_QUATERNION_2: UniqueId = 11;
|
||||
pub const STR_QUATERNION_3: UniqueId = 12;
|
||||
pub const STR_QUATERNION_4: UniqueId = 13;
|
||||
|
||||
pub const AOCS_HK_NUM_OF_ELEMENTS: usize = 13 * 8;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum AocsHkIds {
|
||||
TestAocsSet = 1,
|
||||
@ -85,6 +89,24 @@ impl AocsDataMap {
|
||||
pub fn get_value(&self, id: UniqueId) -> Option<&AocsDataType> {
|
||||
self.map.get(&id)
|
||||
}
|
||||
|
||||
pub fn all_values_as_bytes(&self) -> [u8; AOCS_HK_NUM_OF_ELEMENTS] {
|
||||
let mut buf: [u8; AOCS_HK_NUM_OF_ELEMENTS] = [0; AOCS_HK_NUM_OF_ELEMENTS];
|
||||
let mut i = 0;
|
||||
let map = self.map.clone();
|
||||
let mut map_as_vec = map.keys().collect::<Vec<&UniqueId>>();
|
||||
map_as_vec.sort();
|
||||
for element in map_as_vec {
|
||||
match map.get(element).unwrap() {
|
||||
float_value(val) => {
|
||||
let val_as_byte = BigEndian::write_f64(&mut (buf[i..i + 8]), *val);
|
||||
}
|
||||
}
|
||||
i += 8;
|
||||
}
|
||||
debug!("{:?}", buf);
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumIter, PartialEq, Copy, Clone)]
|
||||
@ -92,52 +114,6 @@ pub enum AocsDataType {
|
||||
float_value(f64),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AOCSSensorData {
|
||||
mgm_data: MGMData, // Voltage for 3 axis
|
||||
css_data: CSSData, // 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 = CSSData::default();
|
||||
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 update_css_data(&mut self, css_data: &Arc<Mutex<CSSData>>) {
|
||||
let data = css_data.lock().unwrap();
|
||||
self.css_data = *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) -> CSSData {
|
||||
self.css_data
|
||||
}
|
||||
|
||||
pub fn read_str_data(&mut self) -> [f64; 4] {
|
||||
self.str_data
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AocsHousekeeper {
|
||||
data_map: Arc<Mutex<AocsDataMap>>,
|
||||
id_list: Vec<UniqueId>,
|
||||
@ -147,6 +123,9 @@ pub struct AocsHousekeeper {
|
||||
aocs_tm_funnel_tx: Sender<StoreAddr>,
|
||||
verif_reporter: VerificationReporterWithSender<MpscPusInStoreSendError>,
|
||||
periodic_hk_ids: Option<Vec<UniqueId>>,
|
||||
periodic_on: bool,
|
||||
prev_time_step: TimeProvider,
|
||||
collection_interval: Duration,
|
||||
}
|
||||
|
||||
impl AocsHousekeeper {
|
||||
@ -183,9 +162,61 @@ impl AocsHousekeeper {
|
||||
aocs_tm_funnel_tx,
|
||||
verif_reporter,
|
||||
periodic_hk_ids: None,
|
||||
periodic_on: false,
|
||||
prev_time_step: TimeProvider::from_now_with_u16_days().unwrap(),
|
||||
collection_interval: Duration::seconds(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_collection_interval(
|
||||
sensor_data_pool: Arc<Mutex<AocsDataMap>>,
|
||||
request_rx: Receiver<RequestWithToken>,
|
||||
seq_count_provider: SeqCountProviderSyncClonable,
|
||||
aocs_tm_store: TmStore,
|
||||
aocs_tm_funnel_tx: Sender<StoreAddr>,
|
||||
verif_reporter: VerificationReporterWithSender<MpscPusInStoreSendError>,
|
||||
collection_interval: Duration,
|
||||
) -> AocsHousekeeper {
|
||||
let id_list = vec![
|
||||
MGM_VOLTAGE_1,
|
||||
MGM_VOLTAGE_2,
|
||||
MGM_VOLTAGE_3,
|
||||
CSS_VOLTAGE_1,
|
||||
CSS_VOLTAGE_2,
|
||||
CSS_VOLTAGE_3,
|
||||
CSS_VOLTAGE_4,
|
||||
CSS_VOLTAGE_5,
|
||||
CSS_VOLTAGE_6,
|
||||
STR_QUATERNION_1,
|
||||
STR_QUATERNION_2,
|
||||
STR_QUATERNION_3,
|
||||
STR_QUATERNION_4,
|
||||
];
|
||||
|
||||
AocsHousekeeper {
|
||||
data_map: sensor_data_pool,
|
||||
id_list,
|
||||
request_rx,
|
||||
seq_count_provider,
|
||||
aocs_tm_store,
|
||||
aocs_tm_funnel_tx,
|
||||
verif_reporter,
|
||||
periodic_hk_ids: None,
|
||||
periodic_on: false,
|
||||
prev_time_step: TimeProvider::from_now_with_u16_days().unwrap(),
|
||||
collection_interval,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn periodic_op(&mut self) {
|
||||
self.handle_hk_request();
|
||||
self.periodic_hk();
|
||||
}
|
||||
|
||||
// housekeeper has methods for both sending individual variables as tm as well as entire aocs data set
|
||||
// individual values results in way too much traffic, therefore is not used
|
||||
// the functions for it are kept here since the logic could be easily adapted to send different sets (something which is currently not implemented)
|
||||
// for now, ..._individual functions are rather unnecessary
|
||||
pub fn handle_hk_request(&mut self) {
|
||||
let mut time_stamp_buf: [u8; 7] = [0; 7];
|
||||
|
||||
@ -198,9 +229,9 @@ impl AocsHousekeeper {
|
||||
.start_success(request_with_token.1.unwrap(), 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::OneShot(id) => self.one_shot(),
|
||||
HkRequest::Enable(id) => self.enable_periodic(),
|
||||
HkRequest::Disable(id) => self.disable_periodic(),
|
||||
HkRequest::ModifyCollectionInterval(_id, _collection_interval) => Ok(()),
|
||||
} {
|
||||
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
|
||||
@ -226,7 +257,24 @@ impl AocsHousekeeper {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_period(&mut self) -> bool {
|
||||
let current_time = TimeProvider::from_now_with_u16_days().unwrap();
|
||||
let prev_time = self.prev_time_step.clone();
|
||||
let delta = current_time.date_time().unwrap() - prev_time.date_time().unwrap();
|
||||
delta > self.collection_interval
|
||||
}
|
||||
|
||||
pub fn periodic_hk(&mut self) {
|
||||
if self.periodic_on && self.check_period() {
|
||||
self.prev_time_step = TimeProvider::from_now_with_u16_days().unwrap();
|
||||
let map = self.data_map.lock().unwrap();
|
||||
let mut data_as_bytes = map.all_values_as_bytes();
|
||||
drop(map);
|
||||
self.send_hk_packet(1, &mut data_as_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn periodic_hk_individual(&mut self) {
|
||||
//let json_string = self.aocs_data_to_str();
|
||||
let data = self.data_map.lock().unwrap();
|
||||
let data_copy = data.clone();
|
||||
@ -242,7 +290,16 @@ impl AocsHousekeeper {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn one_shot_hk(&mut self, id: UniqueId) -> Result<(), ()> {
|
||||
pub fn one_shot(&mut self) -> Result<(), ()> {
|
||||
let map = self.data_map.lock().unwrap();
|
||||
let data_as_bytes = map.all_values_as_bytes();
|
||||
drop(map);
|
||||
// currently gives 1 as id, meaning one is the spid, if multiple spids in this housekeeper, this needs to change!
|
||||
self.send_hk_packet(1, &data_as_bytes);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn one_shot_hk_individual(&mut self, id: UniqueId) -> Result<(), ()> {
|
||||
let data = self.data_map.lock().unwrap();
|
||||
let data_copy = data.clone();
|
||||
drop(data);
|
||||
@ -255,7 +312,12 @@ impl AocsHousekeeper {
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn enable_hk(&mut self, id: UniqueId) -> Result<(), ()> {
|
||||
pub fn enable_periodic(&mut self) -> Result<(), ()> {
|
||||
self.periodic_on = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn enable_periodic_individual(&mut self, id: UniqueId) -> Result<(), ()> {
|
||||
if !self.id_list.contains(&id) {
|
||||
return Err(());
|
||||
}
|
||||
@ -271,7 +333,12 @@ impl AocsHousekeeper {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable_hk(&mut self, id: UniqueId) -> Result<(), ()> {
|
||||
pub fn disable_periodic(&mut self) -> Result<(), ()> {
|
||||
self.periodic_on = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable_periodic_individual(&mut self, id: UniqueId) -> Result<(), ()> {
|
||||
if !self.id_list.contains(&id) {
|
||||
return Err(());
|
||||
}
|
||||
@ -333,11 +400,13 @@ impl AocsHousekeeper {
|
||||
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
|
||||
cds_stamp.write_to_bytes(&mut time_stamp_buf).unwrap();
|
||||
huge_buf[0..4].copy_from_slice(&id.to_be_bytes());
|
||||
let mut len = 4;
|
||||
huge_buf[8..data.len() + 8].copy_from_slice(data);
|
||||
let mut len = 8;
|
||||
huge_buf[len..data.len() + 8].copy_from_slice(data);
|
||||
len += data.len();
|
||||
let data = huge_buf[0..len].to_vec();
|
||||
let tm_sec_header =
|
||||
PusTmSecondaryHeader::new_simple(3, Subservice::TmHkPacket as u8, &time_stamp_buf);
|
||||
sp_header.data_len = len as u16;
|
||||
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");
|
||||
|
90
src/main.rs
90
src/main.rs
@ -9,6 +9,7 @@ mod cam;
|
||||
mod can;
|
||||
mod can_ids;
|
||||
mod ccsds;
|
||||
mod helpers;
|
||||
mod hk;
|
||||
mod logger;
|
||||
mod messages;
|
||||
@ -43,6 +44,7 @@ use strum::IntoEnumIterator;
|
||||
use crate::can_ids::{
|
||||
load_package_id_to_apids, load_package_id_to_threads, DeviceId, PackageModel, ThreadId,
|
||||
};
|
||||
use chrono::Duration;
|
||||
use log::info;
|
||||
use satrs_core::power::{SwitchId, SwitchState};
|
||||
use std::collections::HashMap;
|
||||
@ -51,10 +53,11 @@ use std::sync::mpsc::channel;
|
||||
use std::sync::{mpsc, Arc, Mutex, RwLock};
|
||||
use std::thread;
|
||||
//use libc::time64_t;
|
||||
use crate::aocs::{core_aocs_loop, MGMData, MGMHandler};
|
||||
use crate::aocs::{core_aocs_loop, AocsController, MGMHandler};
|
||||
#[cfg(feature = "can")]
|
||||
use crate::can::CanTxHandler;
|
||||
use crate::hk::{AOCSSensorData, AocsDataMap, AocsHousekeeper};
|
||||
use crate::helpers::{ModeHelper, VerifHelper};
|
||||
use crate::hk::{AocsDataMap, AocsDataType, AocsHousekeeper};
|
||||
use crate::pld_handler::core_pld_task;
|
||||
use crate::power_handler::{core_power_task, PowerSwitcher};
|
||||
|
||||
@ -87,7 +90,7 @@ fn main() {
|
||||
|
||||
let seq_count_provider = SeqCountProviderSyncClonable::default();
|
||||
let msg_count_provider = SeqCountProviderSyncClonable::default();
|
||||
let aocs_seq_count_provider = seq_count_provider.clone();
|
||||
let aocs_seq_count_provider = SeqCountProviderSyncClonable::default();
|
||||
let verif_seq_count_provider = seq_count_provider.clone();
|
||||
let tmtc_seq_count_provider = seq_count_provider.clone();
|
||||
|
||||
@ -159,7 +162,7 @@ fn main() {
|
||||
// Create clones here to allow moving the values
|
||||
let core_args = OtherArgs {
|
||||
sock_addr,
|
||||
verif_reporter,
|
||||
verif_reporter: verif_reporter.clone(),
|
||||
event_sender,
|
||||
event_request_tx,
|
||||
request_map,
|
||||
@ -293,27 +296,84 @@ fn main() {
|
||||
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_data = Arc::new(Mutex::new(AocsDataMap::new()));
|
||||
let (mgm_action_tx, mgm_action_rx) = channel::<RequestWithToken>();
|
||||
let mut aocs_data_not_threadsafe = AocsDataMap::new();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(1, AocsDataType::float_value(1.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(2, AocsDataType::float_value(2.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(3, AocsDataType::float_value(3.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(4, AocsDataType::float_value(4.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(5, AocsDataType::float_value(5.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(6, AocsDataType::float_value(6.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(7, AocsDataType::float_value(7.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(8, AocsDataType::float_value(8.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(9, AocsDataType::float_value(9.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(10, AocsDataType::float_value(10.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(11, AocsDataType::float_value(11.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(12, AocsDataType::float_value(12.0))
|
||||
.unwrap();
|
||||
aocs_data_not_threadsafe
|
||||
.update_value(13, AocsDataType::float_value(13.0))
|
||||
.unwrap();
|
||||
let aocs_data = Arc::new(Mutex::new(aocs_data_not_threadsafe));
|
||||
|
||||
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 aocs_housekeeper = AocsHousekeeper::new(
|
||||
aocs_data,
|
||||
let mut aocs_housekeeper = AocsHousekeeper::new_with_collection_interval(
|
||||
aocs_data.clone(),
|
||||
aocs_hk_rx,
|
||||
aocs_seq_count_provider,
|
||||
aocs_tm_store,
|
||||
aocs_tm_funnel_tx,
|
||||
reporter_aocs,
|
||||
aocs_seq_count_provider.clone(),
|
||||
aocs_tm_store.clone(),
|
||||
aocs_tm_funnel_tx.clone(),
|
||||
reporter_aocs.clone(),
|
||||
Duration::seconds(1),
|
||||
);
|
||||
|
||||
let aocs_controller_verif_helper = VerifHelper::new(verif_reporter.clone());
|
||||
let aocs_controller_mode_helper = ModeHelper::new(
|
||||
AOCS_APID,
|
||||
aocs_seq_count_provider.clone(),
|
||||
aocs_tm_store.clone(),
|
||||
aocs_tm_funnel_tx.clone(),
|
||||
);
|
||||
|
||||
let mut aocs_controller = AocsController::new(
|
||||
aocs_thread_rx,
|
||||
mgm_tx,
|
||||
css_tx,
|
||||
str_tx,
|
||||
aocs_seq_count_provider.clone(),
|
||||
aocs_controller_verif_helper,
|
||||
aocs_controller_mode_helper,
|
||||
);
|
||||
|
||||
loop {
|
||||
aocs_housekeeper.handle_hk_request();
|
||||
aocs_housekeeper.periodic_op();
|
||||
aocs_controller.periodic_op();
|
||||
}
|
||||
/*let mut mgm_handler = MGMHandler::new(
|
||||
power_switcher_aocs.clone(),
|
||||
|
@ -257,6 +257,8 @@ pub fn core_pld_task(
|
||||
debug!("{:?}", camera_handler.get_mode());
|
||||
while camera_handler.get_mode() != CameraMode::Idle {
|
||||
camera_handler.periodic_op();
|
||||
debug!("{:?}", camera_handler.get_mode());
|
||||
sleep(Duration::from_millis(1000));
|
||||
}
|
||||
|
||||
let cds_stamp = TimeProvider::from_now_with_u16_days().unwrap();
|
||||
|
84
src/pus.rs
84
src/pus.rs
@ -21,6 +21,7 @@ use satrs_core::pus::verification::{
|
||||
};
|
||||
use satrs_core::pus::{event, GenericTcCheckError};
|
||||
use satrs_core::res_code::ResultU16;
|
||||
use satrs_core::seq_count::{SeqCountProviderSyncClonable, SequenceCountProviderCore};
|
||||
use satrs_core::spacepackets::ecss::{scheduling, PusServiceId};
|
||||
use satrs_core::spacepackets::CcsdsPacket;
|
||||
use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper;
|
||||
@ -35,7 +36,6 @@ use std::convert::TryFrom;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use satrs_core::seq_count::{SeqCountProviderSyncClonable, SequenceCountProviderCore};
|
||||
|
||||
pub struct PusReceiver {
|
||||
pub tm_helper: PusTmWithCdsShortHelper,
|
||||
@ -178,7 +178,23 @@ impl PusServiceProvider for PusReceiver {
|
||||
}
|
||||
} {
|
||||
if let Some(sender) = self.tc_args.apid_map.clone().get(&apid) {
|
||||
sender.send(request).expect("error sending request");
|
||||
info!("sending request to apid: {}", apid);
|
||||
sender
|
||||
.send(request)
|
||||
.expect(&format!("error sending request to apid {}", apid));
|
||||
} else {
|
||||
let token = request.1.unwrap();
|
||||
self.tm_args
|
||||
.verif_reporter
|
||||
.start_failure(
|
||||
token,
|
||||
FailParams::new(
|
||||
Some(self.stamp_helper.stamp()),
|
||||
&tmtc_err::INVALID_PUS_SUBSERVICE,
|
||||
None,
|
||||
),
|
||||
)
|
||||
.expect("error sending start failure");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -200,7 +216,12 @@ impl PusReceiver {
|
||||
.verif_reporter
|
||||
.start_success(token, Some(self.stamp_helper.stamp()))
|
||||
.expect("Error sending start success");
|
||||
let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None, self.tm_args.seq_count_provider.get());
|
||||
let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(
|
||||
17,
|
||||
2,
|
||||
None,
|
||||
self.tm_args.seq_count_provider.get(),
|
||||
);
|
||||
let addr = self.tm_args.tm_store.add_pus_tm(&ping_reply);
|
||||
self.tm_args
|
||||
.tm_tx
|
||||
@ -306,7 +327,7 @@ impl PusReceiver {
|
||||
Some(HkRequest::Enable(unique_id))
|
||||
} else if PusPacket::subservice(pus_tc) == hk::Subservice::TcDisableHkGeneration as u8 {
|
||||
//send_request(HkRequest::Disable(addressable_id));
|
||||
Some(HkRequest::Enable(unique_id))
|
||||
Some(HkRequest::Disable(unique_id))
|
||||
} else if PusPacket::subservice(pus_tc) == hk::Subservice::TcGenerateOneShotHk as u8 {
|
||||
//send_request(HkRequest::OneShot(addressable_id));
|
||||
Some(HkRequest::OneShot(unique_id))
|
||||
@ -560,7 +581,7 @@ impl PusReceiver {
|
||||
if app_data.is_some() {
|
||||
app_data_len = pus_tc.user_data().unwrap().len();
|
||||
}
|
||||
if app_data_len < 4 {
|
||||
/*if app_data_len < 4 {
|
||||
self.tm_args
|
||||
.verif_reporter
|
||||
.start_failure(
|
||||
@ -573,6 +594,8 @@ impl PusReceiver {
|
||||
)
|
||||
.expect("Sending start failure TM failed");
|
||||
}
|
||||
|
||||
*/
|
||||
let app_data = app_data.unwrap();
|
||||
let mut invalid_subservice_handler = || {
|
||||
self.tm_args
|
||||
@ -589,6 +612,7 @@ impl PusReceiver {
|
||||
};
|
||||
let subservice = mode::Subservice::try_from(PusPacket::subservice(pus_tc));
|
||||
if let Ok(subservice) = subservice {
|
||||
/*
|
||||
let forward_mode_request = |target_id, mode_request: ModeRequest| match self
|
||||
.tc_args
|
||||
.request_map
|
||||
@ -604,11 +628,12 @@ impl PusReceiver {
|
||||
.expect("sending mode request failed");
|
||||
}
|
||||
};
|
||||
*/
|
||||
let mut valid_subservice = true;
|
||||
match subservice {
|
||||
let request = match subservice {
|
||||
Subservice::TcSetMode => {
|
||||
let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
let min_len = ModeAndSubmode::raw_len() + 4;
|
||||
//let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
let min_len = ModeAndSubmode::raw_len();
|
||||
if app_data_len < min_len {
|
||||
self.tm_args
|
||||
.verif_reporter
|
||||
@ -627,37 +652,56 @@ impl PusReceiver {
|
||||
}
|
||||
// Should never fail after size check
|
||||
let mode_submode = ModeAndSubmode::from_be_bytes(
|
||||
app_data[4..4 + ModeAndSubmode::raw_len()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
app_data[0..ModeAndSubmode::raw_len()].try_into().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
forward_mode_request(target_id, ModeRequest::SetMode(mode_submode));
|
||||
info!("{:?}", mode_submode);
|
||||
//forward_mode_request(target_id, ModeRequest::SetMode(mode_submode));
|
||||
Some(RequestWithToken(
|
||||
Request::ModeRequest(ModeRequest::SetMode(mode_submode)),
|
||||
Some(token),
|
||||
))
|
||||
}
|
||||
Subservice::TcReadMode => {
|
||||
let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
forward_mode_request(target_id, ModeRequest::ReadMode);
|
||||
//let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
//forward_mode_request(target_id, ModeRequest::ReadMode);
|
||||
Some(RequestWithToken(
|
||||
Request::ModeRequest(ModeRequest::ReadMode),
|
||||
Some(token),
|
||||
))
|
||||
}
|
||||
Subservice::TcAnnounceMode => {
|
||||
let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
forward_mode_request(target_id, ModeRequest::AnnounceMode);
|
||||
//let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
//forward_mode_request(target_id, ModeRequest::AnnounceMode);
|
||||
Some(RequestWithToken(
|
||||
Request::ModeRequest(ModeRequest::AnnounceMode),
|
||||
Some(token),
|
||||
))
|
||||
}
|
||||
Subservice::TcAnnounceModeRecursive => {
|
||||
let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
forward_mode_request(target_id, ModeRequest::AnnounceModeRecursive);
|
||||
//let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap());
|
||||
//forward_mode_request(target_id, ModeRequest::AnnounceModeRecursive);
|
||||
Some(RequestWithToken(
|
||||
Request::ModeRequest(ModeRequest::AnnounceModeRecursive),
|
||||
Some(token),
|
||||
))
|
||||
}
|
||||
_ => {
|
||||
warn!("Can not process mode request with subservice {subservice:?}");
|
||||
invalid_subservice_handler();
|
||||
valid_subservice = false;
|
||||
None
|
||||
}
|
||||
}
|
||||
if valid_subservice {
|
||||
};
|
||||
return request;
|
||||
/*if valid_subservice {
|
||||
self.tm_args
|
||||
.verif_reporter
|
||||
.start_success(token, Some(self.stamp_helper.stamp()))
|
||||
.expect("sending start success TM failed");
|
||||
}
|
||||
|
||||
*/
|
||||
} else {
|
||||
invalid_subservice_handler();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user