Merge remote-tracking branch 'origin/mueller/acs-ss-init' into mueller/pl-ss
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
2022-10-17 10:52:05 +02:00
200 changed files with 4986 additions and 2265 deletions

View File

@ -6,3 +6,4 @@ add_subdirectory(memory)
add_subdirectory(tmtc)
add_subdirectory(system)
add_subdirectory(csp)
add_subdirectory(cfdp)

View File

@ -0,0 +1 @@

57
mission/cfdp/Config.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef MISSION_CFDP_CONFIG_H_
#define MISSION_CFDP_CONFIG_H_
#include "fsfw/cfdp.h"
namespace cfdp {
class EiveUserHandler : public cfdp::UserBase {
public:
explicit EiveUserHandler(HasFileSystemIF& vfs) : cfdp::UserBase(vfs) {}
virtual ~EiveUserHandler() = default;
void transactionIndication(const cfdp::TransactionId& id) override {}
void eofSentIndication(const cfdp::TransactionId& id) override {}
void transactionFinishedIndication(const cfdp::TransactionFinishedParams& params) override {
sif::info << "File transaction finished for transaction with " << params.id << std::endl;
}
void metadataRecvdIndication(const cfdp::MetadataRecvdParams& params) override {
sif::info << "Metadata received for transaction with " << params.id << std::endl;
}
void fileSegmentRecvdIndication(const cfdp::FileSegmentRecvdParams& params) override {}
void reportIndication(const cfdp::TransactionId& id, cfdp::StatusReportIF& report) override {}
void suspendedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code) override {}
void resumedIndication(const cfdp::TransactionId& id, size_t progress) override {}
void faultIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
size_t progress) override {}
void abandonedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
size_t progress) override {}
void eofRecvIndication(const cfdp::TransactionId& id) override {
sif::info << "EOF PDU received for transaction with " << id << std::endl;
}
};
class EiveFaultHandler : public cfdp::FaultHandlerBase {
public:
void noticeOfSuspensionCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Notice of suspension detected for transaction " << id
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
void noticeOfCancellationCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Notice of suspension detected for transaction " << id
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
void abandonCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Transaction " << id
<< " was abandoned, condition code : " << cfdp::getConditionCodeString(code)
<< std::endl;
}
void ignoreCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Fault ignored for transaction " << id
<< ", condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
};
} // namespace cfdp
#endif /* MISSION_CFDP_CONFIG_H_ */

View File

@ -3,7 +3,7 @@
#include <fsfw/datapool/PoolReadGuard.h>
AcsController::AcsController(object_id_t objectId)
: ExtendedControllerBase(objectId, objects::NO_OBJECT), mgmData(this) {}
: ExtendedControllerBase(objectId), mgmData(this) {}
ReturnValue_t AcsController::handleCommandMessage(CommandMessage *message) {
return returnvalue::OK;
@ -45,7 +45,7 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_3_RM3100_UT, &mgm3PoolVec);
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_IMTQ_CAL_NT, &imtqMgmPoolVec);
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_IMTQ_CAL_ACT_STATUS, &imtqCalActStatus);
poolManager.subscribeForRegularPeriodicPacket({mgmData.getSid(), 5.0});
poolManager.subscribeForRegularPeriodicPacket({mgmData.getSid(), false, 5.0});
return returnvalue::OK;
}

View File

@ -1,10 +1,10 @@
#ifndef MISSION_CONTROLLER_ACSCONTROLLER_H_
#define MISSION_CONTROLLER_ACSCONTROLLER_H_
#include <commonObjects.h>
#include <fsfw/controller/ExtendedControllerBase.h>
#include "controllerdefinitions/AcsCtrlDefinitions.h"
#include "eive/objects.h"
#include "fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h"
#include "fsfw_hal/devicehandlers/MgmRM3100Handler.h"
#include "mission/devices/devicedefinitions/IMTQHandlerDefinitions.h"
@ -33,7 +33,7 @@ class AcsController : public ExtendedControllerBase {
uint32_t* msToReachTheMode) override;
// MGMs
acsctrl::MgmData mgmData;
acsctrl::MgmDataRaw mgmData;
MGMLIS3MDL::MgmPrimaryDataset mgm0Lis3Set =
MGMLIS3MDL::MgmPrimaryDataset(objects::MGM_0_LIS3_HANDLER);

View File

@ -14,8 +14,8 @@
#include <mission/devices/devicedefinitions/payloadPcduDefinitions.h>
#include <objects/systemObjectList.h>
ThermalController::ThermalController(object_id_t objectId, object_id_t parentId)
: ExtendedControllerBase(objectId, parentId),
ThermalController::ThermalController(object_id_t objectId)
: ExtendedControllerBase(objectId),
sensorTemperatures(this),
susTemperatures(this),
deviceTemperatures(this),
@ -234,274 +234,339 @@ ReturnValue_t ThermalController::checkModeCommand(Mode_t mode, Submode_t submode
}
void ThermalController::copySensors() {
PoolReadGuard pg0(&max31865Set0);
if (pg0.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_ploc_heatspreader.value = max31865Set0.temperatureCelcius.value;
sensorTemperatures.sensor_ploc_heatspreader.setValid(max31865Set0.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_ploc_heatspreader.isValid()) {
sensorTemperatures.sensor_ploc_heatspreader.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg0(&max31865Set0);
if (pg0.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_ploc_heatspreader.value = max31865Set0.temperatureCelcius.value;
sensorTemperatures.sensor_ploc_heatspreader.setValid(
max31865Set0.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_ploc_heatspreader.isValid()) {
sensorTemperatures.sensor_ploc_heatspreader.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg1(&max31865Set1);
if (pg1.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_ploc_missionboard.value = max31865Set1.temperatureCelcius.value;
sensorTemperatures.sensor_ploc_missionboard.setValid(max31865Set1.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_ploc_missionboard.isValid()) {
sensorTemperatures.sensor_ploc_missionboard.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg1(&max31865Set1);
if (pg1.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_ploc_missionboard.value = max31865Set1.temperatureCelcius.value;
sensorTemperatures.sensor_ploc_missionboard.setValid(
max31865Set1.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_ploc_missionboard.isValid()) {
sensorTemperatures.sensor_ploc_missionboard.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg2(&max31865Set2);
if (pg2.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_4k_camera.value = max31865Set2.temperatureCelcius.value;
sensorTemperatures.sensor_4k_camera.setValid(max31865Set2.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_4k_camera.isValid()) {
sensorTemperatures.sensor_4k_camera.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg2(&max31865Set2);
if (pg2.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_4k_camera.value = max31865Set2.temperatureCelcius.value;
sensorTemperatures.sensor_4k_camera.setValid(max31865Set2.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_4k_camera.isValid()) {
sensorTemperatures.sensor_4k_camera.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg3(&max31865Set3);
if (pg3.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_dac_heatspreader.value = max31865Set3.temperatureCelcius.value;
sensorTemperatures.sensor_dac_heatspreader.setValid(max31865Set3.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_dac_heatspreader.isValid()) {
sensorTemperatures.sensor_dac_heatspreader.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg3(&max31865Set3);
if (pg3.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_dac_heatspreader.value = max31865Set3.temperatureCelcius.value;
sensorTemperatures.sensor_dac_heatspreader.setValid(
max31865Set3.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_dac_heatspreader.isValid()) {
sensorTemperatures.sensor_dac_heatspreader.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg4(&max31865Set4);
if (pg4.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_startracker.value = max31865Set4.temperatureCelcius.value;
sensorTemperatures.sensor_startracker.setValid(max31865Set4.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_startracker.isValid()) {
sensorTemperatures.sensor_startracker.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg4(&max31865Set4);
if (pg4.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_startracker.value = max31865Set4.temperatureCelcius.value;
sensorTemperatures.sensor_startracker.setValid(max31865Set4.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_startracker.isValid()) {
sensorTemperatures.sensor_startracker.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg5(&max31865Set5);
if (pg5.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_rw1.value = max31865Set5.temperatureCelcius.value;
sensorTemperatures.sensor_rw1.setValid(max31865Set5.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_rw1.isValid()) {
sensorTemperatures.sensor_rw1.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg5(&max31865Set5);
if (pg5.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_rw1.value = max31865Set5.temperatureCelcius.value;
sensorTemperatures.sensor_rw1.setValid(max31865Set5.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_rw1.isValid()) {
sensorTemperatures.sensor_rw1.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg6(&max31865Set6);
if (pg6.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_dro.value = max31865Set6.temperatureCelcius.value;
sensorTemperatures.sensor_dro.setValid(max31865Set6.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_dro.isValid()) {
sensorTemperatures.sensor_dro.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg6(&max31865Set6);
if (pg6.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_dro.value = max31865Set6.temperatureCelcius.value;
sensorTemperatures.sensor_dro.setValid(max31865Set6.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_dro.isValid()) {
sensorTemperatures.sensor_dro.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg7(&max31865Set7);
if (pg7.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_scex.value = max31865Set7.temperatureCelcius.value;
sensorTemperatures.sensor_scex.setValid(max31865Set7.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_scex.isValid()) {
sensorTemperatures.sensor_scex.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg7(&max31865Set7);
if (pg7.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_scex.value = max31865Set7.temperatureCelcius.value;
sensorTemperatures.sensor_scex.setValid(max31865Set7.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_scex.isValid()) {
sensorTemperatures.sensor_scex.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg8(&max31865Set8);
if (pg8.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_x8.value = max31865Set8.temperatureCelcius.value;
sensorTemperatures.sensor_x8.setValid(max31865Set8.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_x8.isValid()) {
sensorTemperatures.sensor_x8.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg8(&max31865Set8);
if (pg8.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_x8.value = max31865Set8.temperatureCelcius.value;
sensorTemperatures.sensor_x8.setValid(max31865Set8.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_x8.isValid()) {
sensorTemperatures.sensor_x8.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg9(&max31865Set9);
if (pg9.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_hpa.value = max31865Set9.temperatureCelcius.value;
sensorTemperatures.sensor_hpa.setValid(max31865Set9.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_hpa.isValid()) {
sensorTemperatures.sensor_hpa.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg9(&max31865Set9);
if (pg9.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_hpa.value = max31865Set9.temperatureCelcius.value;
sensorTemperatures.sensor_hpa.setValid(max31865Set9.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_hpa.isValid()) {
sensorTemperatures.sensor_hpa.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg10(&max31865Set10);
if (pg10.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tx_modul.value = max31865Set10.temperatureCelcius.value;
sensorTemperatures.sensor_tx_modul.setValid(max31865Set10.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_tx_modul.isValid()) {
sensorTemperatures.sensor_tx_modul.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg10(&max31865Set10);
if (pg10.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tx_modul.value = max31865Set10.temperatureCelcius.value;
sensorTemperatures.sensor_tx_modul.setValid(max31865Set10.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_tx_modul.isValid()) {
sensorTemperatures.sensor_tx_modul.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg11(&max31865Set11);
if (pg11.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_mpa.value = max31865Set11.temperatureCelcius.value;
sensorTemperatures.sensor_mpa.setValid(max31865Set11.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_mpa.isValid()) {
sensorTemperatures.sensor_mpa.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg11(&max31865Set11);
if (pg11.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_mpa.value = max31865Set11.temperatureCelcius.value;
sensorTemperatures.sensor_mpa.setValid(max31865Set11.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_mpa.isValid()) {
sensorTemperatures.sensor_mpa.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg12(&max31865Set12);
if (pg12.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_acu.value = max31865Set12.temperatureCelcius.value;
sensorTemperatures.sensor_acu.setValid(max31865Set12.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_acu.isValid()) {
sensorTemperatures.sensor_acu.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg12(&max31865Set12);
if (pg12.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_acu.value = max31865Set12.temperatureCelcius.value;
sensorTemperatures.sensor_acu.setValid(max31865Set12.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_acu.isValid()) {
sensorTemperatures.sensor_acu.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg13(&max31865Set13);
if (pg13.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_plpcdu_heatspreader.value = max31865Set13.temperatureCelcius.value;
sensorTemperatures.sensor_plpcdu_heatspreader.setValid(
max31865Set13.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_plpcdu_heatspreader.isValid()) {
sensorTemperatures.sensor_plpcdu_heatspreader.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg13(&max31865Set13);
if (pg13.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_plpcdu_heatspreader.value = max31865Set13.temperatureCelcius.value;
sensorTemperatures.sensor_plpcdu_heatspreader.setValid(
max31865Set13.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_plpcdu_heatspreader.isValid()) {
sensorTemperatures.sensor_plpcdu_heatspreader.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg14(&max31865Set14);
if (pg14.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tcs_board.value = max31865Set14.temperatureCelcius.value;
sensorTemperatures.sensor_tcs_board.setValid(max31865Set14.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_tcs_board.isValid()) {
sensorTemperatures.sensor_tcs_board.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg14(&max31865Set14);
if (pg14.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tcs_board.value = max31865Set14.temperatureCelcius.value;
sensorTemperatures.sensor_tcs_board.setValid(max31865Set14.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_tcs_board.isValid()) {
sensorTemperatures.sensor_tcs_board.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg15(&max31865Set15);
if (pg15.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_magnettorquer.value = max31865Set15.temperatureCelcius.value;
sensorTemperatures.sensor_magnettorquer.setValid(max31865Set15.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_magnettorquer.isValid()) {
sensorTemperatures.sensor_magnettorquer.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg15(&max31865Set15);
if (pg15.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_magnettorquer.value = max31865Set15.temperatureCelcius.value;
sensorTemperatures.sensor_magnettorquer.setValid(max31865Set15.temperatureCelcius.isValid());
if (not sensorTemperatures.sensor_magnettorquer.isValid()) {
sensorTemperatures.sensor_magnettorquer.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg111(&tmp1075Set1);
if (pg1.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tmp1075_1.value = tmp1075Set1.temperatureCelcius.value;
sensorTemperatures.sensor_tmp1075_1.setValid(tmp1075Set1.temperatureCelcius.isValid());
if (not tmp1075Set1.temperatureCelcius.isValid()) {
sensorTemperatures.sensor_tmp1075_1.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg111(&tmp1075Set1);
if (pg111.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tmp1075_1.value = tmp1075Set1.temperatureCelcius.value;
sensorTemperatures.sensor_tmp1075_1.setValid(tmp1075Set1.temperatureCelcius.isValid());
if (not tmp1075Set1.temperatureCelcius.isValid()) {
sensorTemperatures.sensor_tmp1075_1.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg112(&tmp1075Set2);
if (pg2.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tmp1075_2.value = tmp1075Set2.temperatureCelcius.value;
sensorTemperatures.sensor_tmp1075_2.setValid(tmp1075Set2.temperatureCelcius.isValid());
if (not tmp1075Set2.temperatureCelcius.isValid()) {
sensorTemperatures.sensor_tmp1075_2.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg112(&tmp1075Set2);
if (pg112.getReadResult() == returnvalue::OK) {
sensorTemperatures.sensor_tmp1075_2.value = tmp1075Set2.temperatureCelcius.value;
sensorTemperatures.sensor_tmp1075_2.setValid(tmp1075Set2.temperatureCelcius.isValid());
if (not tmp1075Set2.temperatureCelcius.isValid()) {
sensorTemperatures.sensor_tmp1075_2.value = INVALID_TEMPERATURE;
}
}
}
}
void ThermalController::copySus() {
PoolReadGuard pg0(&susSet0);
if (pg0.getReadResult() == returnvalue::OK) {
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.value = susSet0.temperatureCelcius.value;
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.setValid(susSet0.temperatureCelcius.isValid());
if (not susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.isValid()) {
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg0(&susSet0);
if (pg0.getReadResult() == returnvalue::OK) {
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.value = susSet0.temperatureCelcius.value;
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.setValid(susSet0.temperatureCelcius.isValid());
if (not susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.isValid()) {
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg1(&susSet1);
if (pg1.getReadResult() == returnvalue::OK) {
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.value = susSet1.temperatureCelcius.value;
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.setValid(susSet1.temperatureCelcius.isValid());
if (not susTemperatures.sus_6_r_loc_xfybzm_pt_xf.isValid()) {
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg1(&susSet1);
if (pg1.getReadResult() == returnvalue::OK) {
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.value = susSet1.temperatureCelcius.value;
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.setValid(susSet1.temperatureCelcius.isValid());
if (not susTemperatures.sus_6_r_loc_xfybzm_pt_xf.isValid()) {
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg2(&susSet2);
if (pg2.getReadResult() == returnvalue::OK) {
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.value = susSet2.temperatureCelcius.value;
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.setValid(susSet2.temperatureCelcius.isValid());
if (not susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.isValid()) {
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg2(&susSet2);
if (pg2.getReadResult() == returnvalue::OK) {
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.value = susSet2.temperatureCelcius.value;
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.setValid(susSet2.temperatureCelcius.isValid());
if (not susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.isValid()) {
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg3(&susSet3);
if (pg3.getReadResult() == returnvalue::OK) {
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.value = susSet3.temperatureCelcius.value;
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.setValid(susSet3.temperatureCelcius.isValid());
if (not susTemperatures.sus_7_r_loc_xbybzm_pt_xb.isValid()) {
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg3(&susSet3);
if (pg3.getReadResult() == returnvalue::OK) {
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.value = susSet3.temperatureCelcius.value;
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.setValid(susSet3.temperatureCelcius.isValid());
if (not susTemperatures.sus_7_r_loc_xbybzm_pt_xb.isValid()) {
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg4(&susSet4);
if (pg4.getReadResult() == returnvalue::OK) {
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.value = susSet4.temperatureCelcius.value;
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.setValid(susSet4.temperatureCelcius.isValid());
if (not susTemperatures.sus_2_n_loc_xfybzb_pt_yb.isValid()) {
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg4(&susSet4);
if (pg4.getReadResult() == returnvalue::OK) {
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.value = susSet4.temperatureCelcius.value;
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.setValid(susSet4.temperatureCelcius.isValid());
if (not susTemperatures.sus_2_n_loc_xfybzb_pt_yb.isValid()) {
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg5(&susSet5);
if (pg5.getReadResult() == returnvalue::OK) {
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.value = susSet5.temperatureCelcius.value;
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.setValid(susSet5.temperatureCelcius.isValid());
if (not susTemperatures.sus_8_r_loc_xbybzb_pt_yb.isValid()) {
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg5(&susSet5);
if (pg5.getReadResult() == returnvalue::OK) {
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.value = susSet5.temperatureCelcius.value;
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.setValid(susSet5.temperatureCelcius.isValid());
if (not susTemperatures.sus_8_r_loc_xbybzb_pt_yb.isValid()) {
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg6(&susSet6);
if (pg6.getReadResult() == returnvalue::OK) {
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.value = susSet6.temperatureCelcius.value;
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.setValid(susSet6.temperatureCelcius.isValid());
if (not susTemperatures.sus_3_n_loc_xfybzf_pt_yf.isValid()) {
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg6(&susSet6);
if (pg6.getReadResult() == returnvalue::OK) {
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.value = susSet6.temperatureCelcius.value;
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.setValid(susSet6.temperatureCelcius.isValid());
if (not susTemperatures.sus_3_n_loc_xfybzf_pt_yf.isValid()) {
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg7(&susSet7);
if (pg7.getReadResult() == returnvalue::OK) {
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.value = susSet7.temperatureCelcius.value;
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.setValid(susSet7.temperatureCelcius.isValid());
if (not susTemperatures.sus_9_r_loc_xbybzb_pt_yf.isValid()) {
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg7(&susSet7);
if (pg7.getReadResult() == returnvalue::OK) {
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.value = susSet7.temperatureCelcius.value;
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.setValid(susSet7.temperatureCelcius.isValid());
if (not susTemperatures.sus_9_r_loc_xbybzb_pt_yf.isValid()) {
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg8(&susSet8);
if (pg8.getReadResult() == returnvalue::OK) {
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.value = susSet8.temperatureCelcius.value;
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.setValid(susSet8.temperatureCelcius.isValid());
if (not susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.isValid()) {
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg8(&susSet8);
if (pg8.getReadResult() == returnvalue::OK) {
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.value = susSet8.temperatureCelcius.value;
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.setValid(susSet8.temperatureCelcius.isValid());
if (not susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.isValid()) {
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg9(&susSet9);
if (pg9.getReadResult() == returnvalue::OK) {
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.value = susSet9.temperatureCelcius.value;
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.setValid(susSet9.temperatureCelcius.isValid());
if (not susTemperatures.sus_10_n_loc_xmybzf_pt_zf.isValid()) {
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg9(&susSet9);
if (pg9.getReadResult() == returnvalue::OK) {
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.value = susSet9.temperatureCelcius.value;
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.setValid(susSet9.temperatureCelcius.isValid());
if (not susTemperatures.sus_10_n_loc_xmybzf_pt_zf.isValid()) {
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg10(&susSet10);
if (pg10.getReadResult() == returnvalue::OK) {
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.value = susSet10.temperatureCelcius.value;
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.setValid(susSet10.temperatureCelcius.isValid());
if (not susTemperatures.sus_5_n_loc_xfymzb_pt_zb.isValid()) {
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg10(&susSet10);
if (pg10.getReadResult() == returnvalue::OK) {
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.value = susSet10.temperatureCelcius.value;
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.setValid(susSet10.temperatureCelcius.isValid());
if (not susTemperatures.sus_5_n_loc_xfymzb_pt_zb.isValid()) {
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.value = INVALID_TEMPERATURE;
}
}
}
PoolReadGuard pg11(&susSet11);
if (pg11.getReadResult() == returnvalue::OK) {
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.value = susSet11.temperatureCelcius.value;
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.setValid(susSet11.temperatureCelcius.isValid());
if (not susTemperatures.sus_11_r_loc_xbymzb_pt_zb.isValid()) {
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.value = INVALID_TEMPERATURE;
{
PoolReadGuard pg11(&susSet11);
if (pg11.getReadResult() == returnvalue::OK) {
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.value = susSet11.temperatureCelcius.value;
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.setValid(susSet11.temperatureCelcius.isValid());
if (not susTemperatures.sus_11_r_loc_xbymzb_pt_zb.isValid()) {
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.value = INVALID_TEMPERATURE;
}
}
}
}

View File

@ -12,7 +12,7 @@ class ThermalController : public ExtendedControllerBase {
public:
static const uint16_t INVALID_TEMPERATURE = 999;
ThermalController(object_id_t objectId, object_id_t parentId);
ThermalController(object_id_t objectId);
ReturnValue_t initialize() override;

View File

@ -41,11 +41,11 @@ static constexpr uint8_t MGM_SET_ENTRIES = 10;
static constexpr uint8_t SUS_SET_ENTRIES = 12;
/**
* @brief This dataset can be used to store the collected temperatures of all temperature sensors
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
*/
class MgmData : public StaticLocalDataSet<MGM_SET_ENTRIES> {
class MgmDataRaw : public StaticLocalDataSet<MGM_SET_ENTRIES> {
public:
MgmData(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, MGM_SENSOR_DATA) {}
MgmDataRaw(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, MGM_SENSOR_DATA) {}
// The ACS board measurement are in floating point uT
lp_vec_t<float, 3> mgm0Lis3 = lp_vec_t<float, 3>(sid.objectId, MGM_0_LIS3_UT, this);

View File

@ -1,8 +1,12 @@
#include "GenericFactory.h"
#include <fsfw/cfdp/CfdpDistributor.h>
#include <fsfw/cfdp/handler/CfdpHandler.h>
#include <fsfw/cfdp/handler/RemoteConfigTableIF.h>
#include <fsfw/events/EventManager.h>
#include <fsfw/health/HealthTable.h>
#include <fsfw/internalerror/InternalErrorReporter.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/pus/CService200ModeCommanding.h>
#include <fsfw/pus/CService201HealthCommanding.h>
#include <fsfw/pus/Service17Test.h>
@ -14,16 +18,17 @@
#include <fsfw/pus/Service8FunctionManagement.h>
#include <fsfw/pus/Service9TimeManagement.h>
#include <fsfw/storagemanager/PoolManager.h>
#include <fsfw/tcdistribution/CCSDSDistributor.h>
#include <fsfw/tcdistribution/CcsdsDistributor.h>
#include <fsfw/tcdistribution/PusDistributor.h>
#include <fsfw/timemanager/CdsShortTimeStamper.h>
#include <fsfw_hal/host/HostFilesystem.h>
#include <mission/tmtc/TmFunnel.h>
#include "OBSWConfig.h"
#include "eive/definitions.h"
#include "fsfw/pus/Service11TelecommandScheduling.h"
#include "mission/cfdp/Config.h"
#include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
#if OBSW_ADD_TCPIP_BRIDGE == 1
@ -46,6 +51,19 @@
#define OBSW_TM_TO_PTME 0
#endif
namespace cfdp {
PacketInfoList<64> PACKET_LIST;
LostSegmentsList<128> LOST_SEGMENTS;
EntityId REMOTE_CFDP_ID(UnsignedByteField<uint16_t>(config::EIVE_GROUND_CFDP_ENTITY_ID));
RemoteEntityCfg GROUND_REMOTE_CFG(REMOTE_CFDP_ID);
OneRemoteConfigProvider REMOTE_CFG_PROVIDER(GROUND_REMOTE_CFG);
HostFilesystem HOST_FS;
EiveUserHandler USER_HANDLER(HOST_FS);
EiveFaultHandler EIVE_FAULT_HANDLER;
} // namespace cfdp
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
// Framework objects
new EventManager(objects::EVENT_MANAGER);
@ -56,17 +74,18 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new VerificationReporter();
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
StorageManagerIF* tcStore;
StorageManagerIF* tmStore;
{
PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {300, 32}, {200, 64},
{200, 128}, {100, 1024}, {10, 2048}};
new PoolManager(objects::TC_STORE, poolCfg);
PoolManager::LocalPoolConfig poolCfg = {{200, 16}, {200, 32}, {150, 64},
{100, 128}, {100, 1024}, {100, 2048}};
tcStore = new PoolManager(objects::TC_STORE, poolCfg);
}
{
PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {300, 32}, {100, 64},
{100, 128}, {100, 1024}, {10, 2048}};
new PoolManager(objects::TM_STORE, poolCfg);
{100, 128}, {100, 1024}, {100, 2048}};
tmStore = new PoolManager(objects::TM_STORE, poolCfg);
}
{
@ -75,40 +94,42 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
new PoolManager(objects::IPC_STORE, poolCfg);
}
auto* ccsdsDistrib = new CCSDSDistributor(apid::EIVE_OBSW, objects::CCSDS_PACKET_DISTRIBUTOR);
new PusDistributor(apid::EIVE_OBSW, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
auto* ccsdsDistrib =
new CcsdsDistributor(config::EIVE_PUS_APID, objects::CCSDS_PACKET_DISTRIBUTOR);
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
uint8_t vc = 0;
#if OBSW_TM_TO_PTME == 1
vc = config::LIVE_TM;
#endif
// Every TM packet goes through this funnel
new TmFunnel(objects::TM_FUNNEL, *timeStamper, 50, vc);
auto* funnel = new TmFunnel(objects::TM_FUNNEL, *timeStamper, 50, vc);
// PUS service stack
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, apid::EIVE_OBSW,
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, config::EIVE_PUS_APID,
pus::PUS_SERVICE_1, objects::TM_FUNNEL, 20);
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, apid::EIVE_OBSW,
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, config::EIVE_PUS_APID,
pus::PUS_SERVICE_2, 3, 10);
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, apid::EIVE_OBSW,
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, config::EIVE_PUS_APID,
pus::PUS_SERVICE_3);
new Service5EventReporting(
PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING, apid::EIVE_OBSW, pus::PUS_SERVICE_5), 15,
45);
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, apid::EIVE_OBSW,
pus::PUS_SERVICE_8, 3, 60);
PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING, config::EIVE_PUS_APID, pus::PUS_SERVICE_5),
15, 45);
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, config::EIVE_PUS_APID,
pus::PUS_SERVICE_8, 16, 60);
new Service9TimeManagement(
PsbParams(objects::PUS_SERVICE_9_TIME_MGMT, apid::EIVE_OBSW, pus::PUS_SERVICE_9));
PsbParams(objects::PUS_SERVICE_9_TIME_MGMT, config::EIVE_PUS_APID, pus::PUS_SERVICE_9));
new Service11TelecommandScheduling<common::OBSW_MAX_SCHEDULED_TCS>(
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, apid::EIVE_OBSW, pus::PUS_SERVICE_11),
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, config::EIVE_PUS_APID, pus::PUS_SERVICE_11),
ccsdsDistrib);
new Service17Test(PsbParams(objects::PUS_SERVICE_17_TEST, apid::EIVE_OBSW, pus::PUS_SERVICE_17));
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::EIVE_OBSW,
new Service17Test(
PsbParams(objects::PUS_SERVICE_17_TEST, config::EIVE_PUS_APID, pus::PUS_SERVICE_17));
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, config::EIVE_PUS_APID,
pus::PUS_SERVICE_20);
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, apid::EIVE_OBSW,
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, config::EIVE_PUS_APID,
pus::PUS_SERVICE_200, 8);
new CService201HealthCommanding(objects::PUS_SERVICE_201_HEALTH, apid::EIVE_OBSW,
new CService201HealthCommanding(objects::PUS_SERVICE_201_HEALTH, config::EIVE_PUS_APID,
pus::PUS_SERVICE_201);
#if OBSW_ADD_TCPIP_BRIDGE == 1
#if OBSW_USE_TMTC_TCP_BRIDGE == 0
@ -120,7 +141,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
auto tmtcBridge = new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
auto tcpServer = new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
// TCP is stream based. Use packet ID as start marker when parsing for space packets
tcpServer->setSpacePacketParsingOptions({common::PUS_PACKET_ID});
tcpServer->setSpacePacketParsingOptions({common::PUS_PACKET_ID, common::CFDP_PACKET_ID});
sif::info << "Created TCP server for TMTC commanding with listener port "
<< tcpServer->getTcpPort() << std::endl;
#if OBSW_TCP_SERVER_WIRETAPPING == 1
@ -129,4 +150,25 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
#endif /* OBSW_USE_TMTC_TCP_BRIDGE == 0 */
tmtcBridge->setMaxNumberOfPacketsStored(300);
#endif /* OBSW_ADD_TCPIP_BRIDGE == 1 */
#if OBSW_ADD_CFDP_COMPONENTS == 1
using namespace cfdp;
MessageQueueIF* cfdpMsgQueue = QueueFactory::instance()->createMessageQueue(32);
CfdpDistribCfg distribCfg(objects::CFDP_DISTRIBUTOR, *tcStore, cfdpMsgQueue);
new CfdpDistributor(distribCfg);
auto* msgQueue = QueueFactory::instance()->createMessageQueue(32);
FsfwHandlerParams params(objects::CFDP_HANDLER, HOST_FS, *funnel, *tcStore, *tmStore, *msgQueue);
cfdp::IndicationCfg indicationCfg;
UnsignedByteField<uint16_t> apid(config::EIVE_LOCAL_CFDP_ENTITY_ID);
cfdp::EntityId localId(apid);
GROUND_REMOTE_CFG.defaultChecksum = cfdp::ChecksumType::CRC_32;
CfdpHandlerCfg cfdpCfg(localId, indicationCfg, USER_HANDLER, EIVE_FAULT_HANDLER, PACKET_LIST,
LOST_SEGMENTS, REMOTE_CFG_PROVIDER);
auto* cfdpHandler = new CfdpHandler(params, cfdpCfg);
// All CFDP packets arrive wrapped inside CCSDS space packets
CcsdsDistributorIF::DestInfo info("CFDP Destination", config::EIVE_CFDP_APID,
cfdpHandler->getRequestQueue(), true);
ccsdsDistrib->registerApplication(info);
#endif
}

View File

@ -1,10 +1,11 @@
#include "CspCookie.h"
using namespace GOMSPACE;
CspCookie::CspCookie(uint16_t maxReplyLength_, uint8_t cspAddress_, uint32_t timeoutMs)
: maxReplyLength(maxReplyLength_),
cspAddress(cspAddress_),
timeoutMs(timeoutMs),
reqType(GOMSPACE::DEFAULT_COM_IF) {}
reqType(SpecialRequestTypes::DEFAULT_COM_IF) {}
CspCookie::~CspCookie() {}

View File

@ -28,7 +28,7 @@ class CspCookie : public CookieIF {
uint32_t getTimeout() const;
private:
uint8_t cspPort;
uint8_t cspPort = 0;
uint16_t maxReplyLength;
uint8_t cspAddress;
size_t replyLen = 0;

View File

@ -43,7 +43,7 @@ void ACUHandler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *pack
}
void ACUHandler::letChildHandleConfigReply(DeviceCommandId_t id, const uint8_t *packet) {
handleDeviceTM(packet, ACU::CONFIG_TABLE_SIZE, id);
handleDeviceTm(packet, ACU::CONFIG_TABLE_SIZE, id);
}
LocalPoolDataSetBase *ACUHandler::getDataSetHandle(sid_t sid) {

View File

@ -19,4 +19,7 @@ target_sources(
max1227.cpp
SusHandler.cpp
PayloadPcduHandler.cpp
SolarArrayDeploymentHandler.cpp)
SolarArrayDeploymentHandler.cpp
ScexDeviceHandler.cpp)
add_subdirectory(devicedefinitions)

View File

@ -1,6 +1,5 @@
#include "GomspaceDeviceHandler.h"
#include <common/config/commonObjects.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/globalfunctions/arrayprinter.h>
@ -8,6 +7,7 @@
#include "devicedefinitions/GomSpacePackets.h"
#include "devicedefinitions/powerDefinitions.h"
#include "eive/objects.h"
using namespace GOMSPACE;
@ -44,6 +44,8 @@ ReturnValue_t GomspaceDeviceHandler::buildTransitionDeviceCommand(DeviceCommandI
ReturnValue_t GomspaceDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t* commandData,
size_t commandDataLen) {
auto* cspCookie = dynamic_cast<CspCookie*>(comCookie);
cspCookie->setRequest(SpecialRequestTypes::DEFAULT_COM_IF, 0);
ReturnValue_t result = childCommandHook(deviceCommand, commandData, commandDataLen);
switch (deviceCommand) {
case (GOMSPACE::PING): {
@ -84,37 +86,87 @@ ReturnValue_t GomspaceDeviceHandler::buildCommandFromCommand(DeviceCommandId_t d
break;
}
case (GOMSPACE::REQUEST_HK_TABLE): {
auto reqType = SpecialRequestTypes::DEFAULT_COM_IF;
if (getObjectId() == objects::PDU1_HANDLER or getObjectId() == objects::PDU2_HANDLER) {
reqType = SpecialRequestTypes::GET_PDU_HK;
} else if (getObjectId() == objects::ACU_HANDLER) {
reqType = SpecialRequestTypes::GET_ACU_HK;
} else if (getObjectId() == objects::P60DOCK_HANDLER) {
reqType = SpecialRequestTypes::GET_P60DOCK_HK;
DeviceType devType;
if (getDevType(devType) != returnvalue::OK) {
return returnvalue::FAILED;
}
result = generateRequestFullTableCmd(reqType, GOMSPACE::TableIds::HK, tableCfg.hkTableSize,
deviceCommand);
result =
generateRequestFullHkTableCmd(devType, tableCfg.hkTableSize, deviceCommand, cspCookie);
if (result != returnvalue::OK) {
return result;
}
break;
}
case (GOMSPACE::REQUEST_CONFIG_TABLE): {
auto reqType = SpecialRequestTypes::DEFAULT_COM_IF;
if (getObjectId() == objects::PDU1_HANDLER or getObjectId() == objects::PDU2_HANDLER) {
reqType = SpecialRequestTypes::GET_PDU_CONFIG;
} else if (getObjectId() == objects::ACU_HANDLER) {
reqType = SpecialRequestTypes::GET_ACU_CONFIG;
} else if (getObjectId() == objects::P60DOCK_HANDLER) {
reqType = SpecialRequestTypes::GET_P60DOCK_CONFIG;
DeviceType devType;
if (getDevType(devType) != returnvalue::OK) {
return returnvalue::FAILED;
}
result = generateRequestFullTableCmd(reqType, GOMSPACE::TableIds::CONFIG,
tableCfg.cfgTableSize, deviceCommand);
result =
generateRequestFullCfgTableCmd(devType, tableCfg.cfgTableSize, deviceCommand, cspCookie);
if (result != returnvalue::OK) {
return result;
}
break;
}
case (GOMSPACE::LOAD_TABLE): {
if (commandDataLen != 2) {
return HasActionsIF::INVALID_PARAMETERS;
}
auto* info = reinterpret_cast<GOMSPACE::TableInfo*>(cspPacket);
info->sourceTable = commandData[0];
info->targetTable = commandData[1];
rawPacket = cspPacket;
rawPacketLen = sizeof(GOMSPACE::TableInfo);
cspCookie->setCspPort(CspPorts::P60_PORT_RPARAM_ENUM);
cspCookie->setRequest(SpecialRequestTypes::LOAD_TABLE, 0);
rememberCommandId = deviceCommand;
break;
}
case (GOMSPACE::SAVE_TABLE_FILE): {
if (commandDataLen > 2) {
return HasActionsIF::INVALID_PARAMETERS;
}
auto* info = reinterpret_cast<GOMSPACE::TableInfo*>(cspPacket);
if (commandData[0] != 0 and commandData[0] != 1 and commandData[0] != 2 and
commandData[0] != 4) {
return HasActionsIF::INVALID_PARAMETERS;
}
info->sourceTable = commandData[0];
if (info->sourceTable != 4) {
if (commandDataLen == 2) {
info->targetTable = commandData[1];
} else {
info->targetTable = info->sourceTable;
}
} else {
// Will be ignored, still set the value which is always used
info->targetTable = 4;
}
rawPacket = cspPacket;
rawPacketLen = sizeof(GOMSPACE::TableInfo);
cspCookie->setCspPort(CspPorts::P60_PORT_RPARAM_ENUM);
cspCookie->setRequest(SpecialRequestTypes::SAVE_TABLE, 0);
rememberCommandId = deviceCommand;
break;
}
case (GOMSPACE::SAVE_TABLE_DEFAULT): {
if (commandDataLen != 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
auto* info = reinterpret_cast<GOMSPACE::TableInfo*>(cspPacket);
if (commandData[0] != 0 and commandData[0] != 1 and commandData[0] != 2) {
return HasActionsIF::INVALID_PARAMETERS;
}
info->sourceTable = commandData[0];
info->targetTable = info->sourceTable + 4;
rawPacket = cspPacket;
rawPacketLen = sizeof(GOMSPACE::TableInfo);
cspCookie->setCspPort(CspPorts::P60_PORT_RPARAM_ENUM);
cspCookie->setRequest(SpecialRequestTypes::SAVE_TABLE, 0);
rememberCommandId = deviceCommand;
break;
}
default:
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
@ -131,6 +183,9 @@ void GomspaceDeviceHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(GOMSPACE::GNDWDT_RESET);
this->insertInCommandMap(GOMSPACE::PRINT_SWITCH_V_I);
this->insertInCommandMap(GOMSPACE::PRINT_LATCHUPS);
insertInCommandMap(GOMSPACE::SAVE_TABLE_FILE);
insertInCommandMap(GOMSPACE::SAVE_TABLE_DEFAULT);
insertInCommandMap(GOMSPACE::LOAD_TABLE);
}
ReturnValue_t GomspaceDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize,
@ -177,7 +232,7 @@ ReturnValue_t GomspaceDeviceHandler::interpretDeviceReply(DeviceCommandId_t id,
switch (id) {
case (GOMSPACE::PING): {
SerializeElement<uint32_t> replyTime = *packet;
handleDeviceTM(&replyTime, id, true);
handleDeviceTm(replyTime, true);
break;
}
case (GOMSPACE::PARAM_GET): {
@ -204,7 +259,7 @@ ReturnValue_t GomspaceDeviceHandler::interpretDeviceReply(DeviceCommandId_t id,
uint16_t address = cspGetParamReply.getAddress();
/* Pack relevant information into a tm packet */
ParamReply paramReply(action, tableId, address, payloadLength, tempPayloadBuffer);
handleDeviceTM(&paramReply, id, true);
handleDeviceTm(paramReply, id, true);
break;
}
case (GOMSPACE::PARAM_SET): {
@ -443,6 +498,19 @@ bool GomspaceDeviceHandler::validTableId(uint8_t id) {
return false;
}
ReturnValue_t GomspaceDeviceHandler::getDevType(GOMSPACE::DeviceType& type) const {
if (getObjectId() == objects::PDU1_HANDLER or getObjectId() == objects::PDU2_HANDLER) {
type = DeviceType::PDU;
} else if (getObjectId() == objects::ACU_HANDLER) {
type = DeviceType::ACU;
} else if (getObjectId() == objects::P60DOCK_HANDLER) {
type = DeviceType::P60DOCK;
} else {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t GomspaceDeviceHandler::generateResetWatchdogCmd() {
WatchdogResetCommand watchdogResetCommand;
size_t cspPacketLen = 0;
@ -462,19 +530,40 @@ ReturnValue_t GomspaceDeviceHandler::generateResetWatchdogCmd() {
return returnvalue::OK;
}
ReturnValue_t GomspaceDeviceHandler::generateRequestFullTableCmd(SpecialRequestTypes reqType,
uint8_t tableId,
uint16_t tableReplySize,
DeviceCommandId_t id) {
uint16_t querySize = tableReplySize;
if (reqType == SpecialRequestTypes::DEFAULT_COM_IF) {
sif::warning << "Default communication for table requests not implemented anymore" << std::endl;
return returnvalue::FAILED;
ReturnValue_t GomspaceDeviceHandler::generateRequestFullHkTableCmd(DeviceType dev,
uint16_t tableReplySize,
DeviceCommandId_t id,
CspCookie* cspCookie) {
if (dev == DeviceType::ACU) {
cspCookie->setRequest(SpecialRequestTypes::GET_ACU_HK, tableReplySize);
} else if (dev == DeviceType::P60DOCK) {
cspCookie->setRequest(SpecialRequestTypes::GET_P60DOCK_HK, tableReplySize);
} else if (dev == DeviceType::PDU) {
cspCookie->setRequest(SpecialRequestTypes::GET_PDU_HK, tableReplySize);
}
auto* cspCookie = dynamic_cast<CspCookie*>(comCookie);
cspCookie->setRequest(reqType, tableReplySize);
cspCookie->setCspPort(CspPorts::P60_PORT_RPARAM_ENUM);
rememberRequestedSize = querySize;
rememberRequestedSize = tableReplySize;
rememberCommandId = id;
return returnvalue::OK;
}
ReturnValue_t GomspaceDeviceHandler::generateRequestFullCfgTableCmd(DeviceType dev,
uint16_t tableReplySize,
DeviceCommandId_t id,
CspCookie* cspCookie) {
if (dev == DeviceType::ACU) {
cspCookie->setRequest(SpecialRequestTypes::GET_ACU_CONFIG, tableReplySize);
} else if (dev == DeviceType::P60DOCK) {
cspCookie->setRequest(SpecialRequestTypes::GET_P60DOCK_CONFIG, tableReplySize);
} else if (dev == DeviceType::PDU) {
cspCookie->setRequest(SpecialRequestTypes::GET_PDU_CONFIG, tableReplySize);
}
cspCookie->setCspPort(CspPorts::P60_PORT_RPARAM_ENUM);
// Unfortunately, this does not work..
// cspPacket[0] = defaultTable;
// rawPacket = cspPacket;
// rawPacketLen = 1;
rememberRequestedSize = tableReplySize;
rememberCommandId = id;
return returnvalue::OK;
}

View File

@ -82,10 +82,20 @@ class GomspaceDeviceHandler : public DeviceHandlerBase {
* @brief The command to generate a request to receive the full housekeeping table is device
* specific. Thus the child has to build this command.
*/
virtual ReturnValue_t generateRequestFullTableCmd(GOMSPACE::SpecialRequestTypes reqType,
uint8_t tableId, uint16_t tableSize,
DeviceCommandId_t id);
ReturnValue_t generateRequestFullHkTableCmd(GOMSPACE::DeviceType devType, uint16_t tableSize,
DeviceCommandId_t id, CspCookie *cspCookie);
/**
* Unfortunately, it was not possible to specify the table ID (e.g. request table from
* default store)
* @param devType
* @param tableSize
* @param id
* @param cspCookie
* @return
*/
ReturnValue_t generateRequestFullCfgTableCmd(GOMSPACE::DeviceType devType, uint16_t tableSize,
DeviceCommandId_t id, CspCookie *cspCookie);
ReturnValue_t getDevType(GOMSPACE::DeviceType &type) const;
/**
* This command handles printing the HK table to the console. This is useful for debugging
* purposes

View File

@ -18,6 +18,8 @@
#include <vector>
#include "devices/heaterSwitcherList.h"
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
class PowerSwitchIF;
class HealthTableIF;

View File

@ -20,7 +20,7 @@ IMTQHandler::IMTQHandler(object_id_t objectId, object_id_t comIF, CookieIF* comC
posZselfTestDataset(this),
negZselfTestDataset(this),
switcher(pwrSwitcher) {
if (comCookie == NULL) {
if (comCookie == nullptr) {
sif::error << "IMTQHandler: Invalid com cookie" << std::endl;
}
}

View File

@ -5,6 +5,9 @@
#include <mission/devices/devicedefinitions/IMTQHandlerDefinitions.h>
#include <string.h>
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
/**
* @brief This is the device handler for the ISIS Magnetorquer iMTQ.
*

View File

@ -24,11 +24,6 @@ ReturnValue_t P60DockHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
void P60DockHandler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) {
parseHkTableReply(packet);
/**
* Hk table will be sent to the commander if hk table request was not triggered by the
* P60DockHandler itself.
*/
handleDeviceTM(&coreHk, id, true);
}
void P60DockHandler::parseHkTableReply(const uint8_t *packet) {
@ -273,5 +268,5 @@ void P60DockHandler::printHkTableLatchups() {
void P60DockHandler::setDebugMode(bool enable) { this->debugMode = enable; }
void P60DockHandler::letChildHandleConfigReply(DeviceCommandId_t id, const uint8_t *packet) {
handleDeviceTM(packet, P60Dock::CONFIG_TABLE_SIZE, id);
handleDeviceTm(packet, P60Dock::CONFIG_TABLE_SIZE, id);
}

View File

@ -4,7 +4,7 @@
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include "GomspaceDeviceHandler.h"
#include "commonSubsystemIds.h"
#include "eive/eventSubsystemIds.h"
/**
* @brief Device handler for the P60Dock. The P60Dock serves as carrier for the ACU, PDU1 and

View File

@ -22,7 +22,6 @@ ReturnValue_t PDU1Handler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
void PDU1Handler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) {
parseHkTableReply(packet);
handleDeviceTM(&coreHk, id, true);
}
void PDU1Handler::assignChannelHookFunction(GOMSPACE::ChannelSwitchHook hook, void *args) {
@ -81,7 +80,7 @@ ReturnValue_t PDU1Handler::setParamCallback(SetParamMessageUnpacker &unpacker,
}
void PDU1Handler::letChildHandleConfigReply(DeviceCommandId_t id, const uint8_t *packet) {
handleDeviceTM(packet, PDU::CONFIG_TABLE_SIZE, id);
handleDeviceTm(packet, PDU::CONFIG_TABLE_SIZE, id);
}
void PDU1Handler::parseHkTableReply(const uint8_t *packet) {

View File

@ -22,15 +22,10 @@ ReturnValue_t PDU2Handler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
void PDU2Handler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) {
parseHkTableReply(packet);
/**
* Hk table will be sent to the commander if hk table request was not triggered by the
* PDU2Handler itself.
*/
handleDeviceTM(&coreHk, id, true);
}
void PDU2Handler::letChildHandleConfigReply(DeviceCommandId_t id, const uint8_t *packet) {
handleDeviceTM(packet, PDU::CONFIG_TABLE_SIZE, id);
handleDeviceTm(packet, PDU::CONFIG_TABLE_SIZE, id);
}
void PDU2Handler::assignChannelHookFunction(GOMSPACE::ChannelSwitchHook hook, void *args) {

View File

@ -491,8 +491,8 @@ void PayloadPcduHandler::checkAdcValues() {
void PayloadPcduHandler::checkJsonFileInit() {
if (not jsonFileInitComplete) {
sd::SdCard activeSd = sdcMan->getActiveSdCard();
if (sdcMan->isSdCardMounted(activeSd)) {
auto activeSd = sdcMan->getActiveSdCard();
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
params.initialize(sdcMan->getCurrentMountPrefix());
jsonFileInitComplete = true;
}

View File

@ -6,6 +6,9 @@
#include <mission/devices/devicedefinitions/RwDefinitions.h>
#include <string.h>
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
class GpioIF;
/**

View File

@ -0,0 +1,369 @@
#include "ScexDeviceHandler.h"
#include <linux/devices/ScexHelper.h>
#include <mission/memory/SdCardMountedIF.h>
#include <algorithm>
#include <ctime>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <random>
#include "fsfw/globalfunctions/CRC.h"
#include "mission/devices/devicedefinitions/ScexDefinitions.h"
using std::ofstream;
using namespace returnvalue;
ScexDeviceHandler::ScexDeviceHandler(object_id_t objectId, ScexUartReader& reader, CookieIF* cookie,
SdCardMountedIF& sdcMan)
: DeviceHandlerBase(objectId, reader.getObjectId(), cookie), sdcMan(sdcMan), reader(reader) {}
ScexDeviceHandler::~ScexDeviceHandler() {}
void ScexDeviceHandler::doStartUp() { setMode(MODE_ON); }
void ScexDeviceHandler::doShutDown() {
reader.reset();
commandActive = false;
setMode(_MODE_POWER_DOWN);
}
ReturnValue_t ScexDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { return OK; }
ReturnValue_t ScexDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { return OK; }
ReturnValue_t ScexDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t* commandData,
size_t commandDataLen) {
using namespace scex;
auto cmdTyped = static_cast<scex::Cmds>(deviceCommand);
if (std::find(VALID_CMDS.begin(), VALID_CMDS.end(), deviceCommand) == VALID_CMDS.end()) {
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
bool tempCheck = false;
if (commandDataLen == 1) {
tempCheck = commandData[0];
}
if (commandActive) {
return DeviceHandlerIF::BUSY;
}
switch (deviceCommand) {
case (PING): {
finishCountdown.setTimeout(SHORT_CD);
// countdown starten
finishCountdown.resetTimer();
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
tempCheck);
break;
}
case (EXP_STATUS_CMD): {
finishCountdown.setTimeout(SHORT_CD);
// countdown starten
finishCountdown.resetTimer();
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
tempCheck);
break;
}
case (ION_CMD): {
finishCountdown.setTimeout(SHORT_CD);
// countdown starten
finishCountdown.resetTimer();
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
tempCheck);
break;
}
case (TEMP_CMD): {
finishCountdown.setTimeout(SHORT_CD);
// countdown starten
finishCountdown.resetTimer();
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
tempCheck);
break;
}
case (FRAM): {
finishCountdown.setTimeout(LONG_CD);
// countdown starten
finishCountdown.resetTimer();
if (debugMode) {
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
sif::info << "ScexDeviceHandler::buildCommandFromCommand: RemainingMillis: "
<< remainingMillis << std::endl;
}
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen,
{commandData + 1, commandDataLen - 1}, tempCheck);
updatePeriodicReply(true, deviceCommand);
break;
}
case (ONE_CELL): {
finishCountdown.setTimeout(LONG_CD);
// countdown starts
finishCountdown.resetTimer();
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen,
{commandData + 1, commandDataLen - 1}, tempCheck);
updatePeriodicReply(true, deviceCommand);
break;
}
case (ALL_CELLS_CMD): {
finishCountdown.setTimeout(LONG_CD);
// countdown starts
finishCountdown.resetTimer();
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen,
{commandData + 1, commandDataLen - 1}, tempCheck);
updatePeriodicReply(true, deviceCommand);
break;
}
default: {
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
}
commandActive = true;
rawPacket = cmdBuf.data();
return OK;
}
void ScexDeviceHandler::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(scex::Cmds::PING, 5, nullptr, 0, false, false, 0, &finishCountdown);
insertInCommandAndReplyMap(scex::Cmds::ION_CMD, 3, nullptr, 0, false, false, 0, &finishCountdown);
insertInCommandAndReplyMap(scex::Cmds::TEMP_CMD, 3, nullptr, 0, false, false, 0,
&finishCountdown);
insertInCommandAndReplyMap(scex::Cmds::EXP_STATUS_CMD, 3, nullptr, 0, false, false, 0,
&finishCountdown);
insertInCommandAndReplyMap(scex::Cmds::ALL_CELLS_CMD, 0, nullptr, 0, true, false,
scex::Cmds::ALL_CELLS_CMD, &finishCountdown);
insertInCommandAndReplyMap(scex::Cmds::ONE_CELL, 0, nullptr, 0, true, false, scex::Cmds::ONE_CELL,
&finishCountdown);
insertInCommandAndReplyMap(scex::Cmds::FRAM, 0, nullptr, 0, true, false, scex::Cmds::FRAM,
&finishCountdown);
insertInReplyMap(scex::Cmds::ERROR_REPLY, 3);
}
ReturnValue_t ScexDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize,
DeviceCommandId_t* foundId, size_t* foundLen) {
size_t len = remainingSize;
ReturnValue_t result = helper.deSerialize(&start, &len);
if (result == ScexHelper::INVALID_CRC) {
sif::warning << "ScexDeviceHandler::scanForReply: CRC invalid" << std::endl;
*foundLen = remainingSize;
} else {
result = handleValidReply(remainingSize, foundId, foundLen);
}
return result;
}
ReturnValue_t ScexDeviceHandler::handleValidReply(size_t remSize, DeviceCommandId_t* foundId,
size_t* foundLen) {
using namespace scex;
ReturnValue_t result = OK;
switch (helper.getCmd()) {
case (FRAM): {
if (debugMode) {
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
sif::info << "ScexDeviceHandler::handleValidReply: RemMillis: " << remainingMillis
<< std::endl;
}
finishAction(true, helper.getCmd(), OK);
result = APERIODIC_REPLY;
break;
}
case (ONE_CELL): {
finishAction(true, helper.getCmd(), OK);
result = APERIODIC_REPLY;
break;
}
case (ALL_CELLS_CMD): {
finishAction(true, helper.getCmd(), OK);
result = APERIODIC_REPLY;
break;
}
default: {
break;
}
}
*foundId = helper.getCmd();
*foundLen = remSize;
return result;
}
ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) {
using namespace scex;
ReturnValue_t status = OK;
auto oneFileHandler = [&](std::string cmdName) {
fileId = date_time_string();
std::ostringstream oss;
auto prefix = sdcMan.getCurrentMountPrefix();
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
fileName = oss.str();
ofstream out(fileName, ofstream::binary);
if (out.bad()) {
sif::error << "ScexDeviceHandler::interpretDeviceReply: Could not open file " << fileName
<< std::endl;
return FAILED;
}
out << helper;
return OK;
};
auto multiFileHandler = [&](std::string cmdName) {
if ((helper.getPacketCounter() == 1) or (not fileNameSet)) {
fileId = date_time_string();
std::ostringstream oss;
auto prefix = sdcMan.getCurrentMountPrefix();
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
fileName = oss.str();
fileNameSet = true;
ofstream out(fileName, ofstream::binary);
if (out.bad()) {
sif::error << "ScexDeviceHandler::handleValidReply: Could not open file " << fileName
<< std::endl;
return FAILED;
}
out << helper;
} else {
ofstream out(fileName,
ofstream::binary | ofstream::app); // append
if (out.bad()) {
sif::error << "ScexDeviceHandler::handleValidReply: Could not open file " << fileName
<< std::endl;
return FAILED;
}
out << helper;
}
return OK;
};
switch (id) {
case (PING): {
status = oneFileHandler("ping_");
break;
}
case (ION_CMD): {
status = oneFileHandler("ion_");
break;
}
case (TEMP_CMD): {
status = oneFileHandler("temp_");
break;
}
case (EXP_STATUS_CMD): {
status = oneFileHandler("exp_status_");
break;
}
case (FRAM): {
status = multiFileHandler("fram_");
break;
}
case (ONE_CELL): {
status = multiFileHandler("one_cell_");
break;
}
case (ALL_CELLS_CMD): {
status = multiFileHandler("multi_cell_");
break;
}
default:
// Unknown DeviceCommand
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
if (helper.getPacketCounter() == helper.getTotalPacketCounter()) {
reader.finish();
commandActive = false;
if (id != PING) {
fileNameSet = false;
}
if (id == FRAM or id == ALL_CELLS_CMD or id == ONE_CELL) {
triggerEvent(MULTI_PACKET_COMMAND_DONE, id);
updatePeriodicReply(false, id);
}
}
if (debugMode) {
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
sif::info << __FILE__ << __func__ << "(" << __LINE__ << ") RemMillis: " << remainingMillis
<< std::endl;
}
return status;
}
void ScexDeviceHandler::performOperationHook() {
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
if (commandActive and finishCountdown.hasTimedOut()) {
triggerEvent(scex::EXPERIMENT_TIMEDOUT, currCmd, 0);
reader.finish();
sif::warning << "ScexDeviceHandler::scanForReply: Reader timeout; RemMillis: "
<< remainingMillis << std::endl;
fileNameSet = false;
commandActive = false;
}
}
uint32_t ScexDeviceHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return OK; }
ReturnValue_t ScexDeviceHandler::getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches) {
if (switchId) {
*numberOfSwitches = 1;
*switches = &switchId.value();
}
return OK;
}
ReturnValue_t ScexDeviceHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
return OK;
}
std::string ScexDeviceHandler::date_time_string() {
using namespace std;
string date_time;
Clock::TimeOfDay_t tod;
Clock::getDateAndTime(&tod);
ostringstream oss(std::ostringstream::ate);
if (tod.hour < 10) {
oss << tod.year << tod.month << tod.day << "_0" << tod.hour;
} else {
oss << tod.year << tod.month << tod.day << "_" << tod.hour;
}
if (tod.minute < 10) {
oss << 0 << tod.minute;
} else {
oss << tod.minute;
}
if (tod.second < 10) {
oss << 0 << tod.second;
} else {
oss << tod.second;
}
date_time = oss.str();
return date_time;
}
void ScexDeviceHandler::modeChanged() {}
void ScexDeviceHandler::setPowerSwitcher(PowerSwitchIF& powerSwitcher, power::Switch_t switchId) {
DeviceHandlerBase::setPowerSwitcher(&powerSwitcher);
this->switchId = switchId;
}
ReturnValue_t ScexDeviceHandler::initializeAfterTaskCreation() {
auto mntPrefix = sdcMan.getCurrentMountPrefix();
std::filesystem::path fullFilePath = mntPrefix;
fullFilePath /= "scex";
bool fileExists = std::filesystem::exists(fullFilePath);
if (not fileExists) {
std::filesystem::create_directory(fullFilePath);
}
return DeviceHandlerBase::initializeAfterTaskCreation();
}

View File

@ -0,0 +1,64 @@
#ifndef MISSION_DEVICES_SCEXDEVICEHANDLER_H_
#define MISSION_DEVICES_SCEXDEVICEHANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <linux/devices/ScexHelper.h>
#include <linux/devices/ScexUartReader.h>
#include <optional>
#include "eive/eventSubsystemIds.h"
class SdCardMountedIF;
class ScexDeviceHandler : public DeviceHandlerBase {
public:
ScexDeviceHandler(object_id_t objectId, ScexUartReader &reader, CookieIF *cookie,
SdCardMountedIF &sdcMan);
void setPowerSwitcher(PowerSwitchIF &powerSwitcher, power::Switch_t switchId);
virtual ~ScexDeviceHandler();
private:
static constexpr uint32_t LONG_CD = 180 * 1000;
static constexpr uint32_t SHORT_CD = 12000;
std::array<uint8_t, 64> cmdBuf = {};
std::optional<power::Switch_t> switchId;
std::string fileId = "";
std::string fileName = "";
bool fileNameSet = false;
bool commandActive = false;
bool debugMode = false;
scex::Cmds currCmd = scex::Cmds::PING;
SdCardMountedIF &sdcMan;
Countdown finishCountdown = Countdown(LONG_CD);
std::string date_time_string();
// DeviceHandlerBase private function implementation
void doStartUp() override;
void doShutDown() override;
ScexHelper helper;
ScexUartReader &reader;
void performOperationHook() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override;
void fillCommandAndReplyMap() override;
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId,
size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
ReturnValue_t handleValidReply(size_t remSize, DeviceCommandId_t *foundId, size_t *foundLen);
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
ReturnValue_t initializeAfterTaskCreation() override;
void modeChanged() override;
};
#endif /* MISSION_DEVICES_SCEXDEVICEHANDLER_H_ */

View File

@ -1,171 +1,470 @@
#include "SolarArrayDeploymentHandler.h"
#include <devices/gpioIds.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw_hal/common/gpio/GpioCookie.h>
#include <fsfw/tasks/TaskFactory.h>
SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(
object_id_t setObjectId_, object_id_t gpioDriverId_, CookieIF* gpioCookie_,
object_id_t mainLineSwitcherObjectId_, pcdu::Switches mainLineSwitch_, gpioId_t deplSA1,
gpioId_t deplSA2, uint32_t burnTimeMs)
#include <filesystem>
#include <fstream>
#include <iostream>
#include "devices/gpioIds.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw_hal/common/gpio/GpioCookie.h"
static constexpr bool DEBUG_MODE = true;
SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_,
GpioIF& gpioInterface,
PowerSwitchIF& mainLineSwitcher_,
pcdu::Switches mainLineSwitch_,
gpioId_t deplSA1, gpioId_t deplSA2,
SdCardMountedIF& sdcMountedIF)
: SystemObject(setObjectId_),
gpioDriverId(gpioDriverId_),
gpioCookie(gpioCookie_),
mainLineSwitcherObjectId(mainLineSwitcherObjectId_),
mainLineSwitch(mainLineSwitch_),
gpioInterface(gpioInterface),
deplSA1(deplSA1),
deplSA2(deplSA2),
burnTimeMs(burnTimeMs),
mainLineSwitcher(mainLineSwitcher_),
mainLineSwitch(mainLineSwitch_),
sdcMan(sdcMountedIF),
actionHelper(this, nullptr) {
auto mqArgs = MqArgs(setObjectId_, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
SolarArrayDeploymentHandler::~SolarArrayDeploymentHandler() {}
SolarArrayDeploymentHandler::~SolarArrayDeploymentHandler() = default;
ReturnValue_t SolarArrayDeploymentHandler::performOperation(uint8_t operationCode) {
if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
handleStateMachine();
return returnvalue::OK;
}
return returnvalue::OK;
}
ReturnValue_t SolarArrayDeploymentHandler::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
gpioInterface = ObjectManager::instance()->get<GpioIF>(gpioDriverId);
if (gpioInterface == nullptr) {
sif::error << "SolarArrayDeploymentHandler::initialize: Invalid Gpio interface." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = gpioInterface->addGpios(dynamic_cast<GpioCookie*>(gpioCookie));
if (result != returnvalue::OK) {
sif::error << "SolarArrayDeploymentHandler::initialize: Failed to initialize Gpio interface"
<< std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
if (mainLineSwitcherObjectId != objects::NO_OBJECT) {
mainLineSwitcher = ObjectManager::instance()->get<PowerSwitchIF>(mainLineSwitcherObjectId);
if (mainLineSwitcher == nullptr) {
sif::error
<< "SolarArrayDeploymentHandler::initialize: Main line switcher failed to fetch object"
<< "from object ID." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
using namespace std::filesystem;
if (opDivider.checkAndIncrement()) {
auto activeSdc = sdcMan.getActiveSdCard();
if (activeSdc and activeSdc.value() == sd::SdCard::SLOT_0 and
sdcMan.isSdCardUsable(activeSdc.value())) {
if (exists(SD_0_DEPL_FILE)) {
// perform autonomous deployment handling
performAutonomousDepl(sd::SdCard::SLOT_0, dryRunStringInFile(SD_0_DEPL_FILE));
}
} else if (activeSdc and activeSdc.value() == sd::SdCard::SLOT_1 and
sdcMan.isSdCardUsable(activeSdc.value())) {
if (exists(SD_1_DEPL_FILE)) {
// perform autonomous deployment handling
performAutonomousDepl(sd::SdCard::SLOT_1, dryRunStringInFile(SD_1_DEPL_FILE));
}
} else {
// TODO: This is FDIR domain. If both SD cards are not available for whatever reason,
// there is not much we can do except somehow use the scratch buffer which is
// not non-volatile. Implementation effort is considerable as well.
}
}
result = actionHelper.initialize(commandQueue);
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
readCommandQueue();
handleStateMachine();
return returnvalue::OK;
}
void SolarArrayDeploymentHandler::handleStateMachine() {
switch (stateMachine) {
case WAIT_ON_DELOYMENT_COMMAND:
readCommandQueue();
break;
case SWITCH_8V_ON:
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON);
mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
stateMachine = WAIT_ON_8V_SWITCH;
break;
case WAIT_ON_8V_SWITCH:
performWaitOn8VActions();
break;
case SWITCH_DEPL_GPIOS:
switchDeploymentTransistors();
break;
case WAIT_ON_DEPLOYMENT_FINISH:
handleDeploymentFinish();
break;
case WAIT_FOR_MAIN_SWITCH_OFF:
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_OFF) {
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
} else if (mainSwitchCountdown.hasTimedOut()) {
triggerEvent(MAIN_SWITCH_OFF_TIMEOUT);
sif::error << "SolarArrayDeploymentHandler::handleStateMachine: Failed to switch main"
<< " switch off" << std::endl;
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
if (stateMachine == MAIN_POWER_ON) {
mainLineSwitcher.sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON);
mainSwitchCountdown.setTimeout(mainLineSwitcher.getSwitchDelayMs());
stateMachine = WAIT_MAIN_POWER_ON;
sif::info << "S/A Deployment: Deployment power line on" << std::endl;
}
if (stateMachine == MAIN_POWER_OFF) {
// These should never fail
allOff();
stateMachine = WAIT_MAIN_POWER_OFF;
sif::info << "S/A Deployment: Deployment power line off" << std::endl;
}
if (stateMachine == WAIT_MAIN_POWER_ON) {
if (checkMainPowerOn()) {
if (DEBUG_MODE) {
sif::debug << "SA DEPL FSM: WAIT_MAIN_POWER_ON done -> SWITCH_DEPL_GPIOS" << std::endl;
}
break;
default:
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Invalid state" << std::endl;
break;
stateMachine = SWITCH_DEPL_GPIOS;
}
}
if (stateMachine == WAIT_MAIN_POWER_OFF) {
if (checkMainPowerOff()) {
if (DEBUG_MODE) {
sif::debug << "SA DEPL FSM: WAIT_MAIN_POWER_OFF done -> FSM DONE" << std::endl;
}
sif::info << "S/A Deployment: FSM done" << std::endl;
finishFsm(returnvalue::OK);
}
}
if (stateMachine == SWITCH_DEPL_GPIOS) {
burnCountdown.setTimeout(fsmInfo.burnCountdownMs);
// This should never fail
channelAlternationCd.resetTimer();
if (not fsmInfo.dryRun) {
sa2Off();
sa1On();
fsmInfo.alternationDummy = true;
}
sif::info << "S/A Deployment: Burning" << std::endl;
triggerEvent(BURN_PHASE_START, fsmInfo.burnCountdownMs, fsmInfo.dryRun);
stateMachine = BURNING;
}
if (stateMachine == BURNING) {
saGpioAlternation();
if (burnCountdown.hasTimedOut()) {
if (DEBUG_MODE) {
sif::debug << "SA DEPL FSM: BURNING done -> WAIT_MAIN_POWER_OFF" << std::endl;
}
allOff();
triggerEvent(BURN_PHASE_DONE, fsmInfo.burnCountdownMs, fsmInfo.dryRun);
stateMachine = WAIT_MAIN_POWER_OFF;
}
}
}
void SolarArrayDeploymentHandler::performWaitOn8VActions() {
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_ON) {
stateMachine = SWITCH_DEPL_GPIOS;
ReturnValue_t SolarArrayDeploymentHandler::performAutonomousDepl(sd::SdCard sdCard, bool dryRun) {
using namespace std::filesystem;
using namespace std;
auto initFile = [](const char* filename) {
ofstream of(filename);
of << "phase: init\n";
of << "secs_since_start: 0\n";
};
if (sdCard == sd::SdCard::SLOT_0) {
if (not exists(SD_0_DEPLY_INFO)) {
initFile(SD_0_DEPLY_INFO);
}
if (not autonomousDeplForFile(sd::SdCard::SLOT_0, SD_0_DEPLY_INFO, dryRun)) {
initFile(SD_0_DEPLY_INFO);
}
} else if (sdCard == sd::SdCard::SLOT_1) {
if (not exists(SD_1_DEPLY_INFO)) {
initFile(SD_1_DEPLY_INFO);
}
if (not autonomousDeplForFile(sd::SdCard::SLOT_1, SD_1_DEPLY_INFO, dryRun)) {
initFile(SD_1_DEPLY_INFO);
}
}
return returnvalue::OK;
}
bool SolarArrayDeploymentHandler::autonomousDeplForFile(sd::SdCard sdCard, const char* filename,
bool dryRun) {
using namespace std;
ifstream file(filename);
string line;
string word;
unsigned int lineNum = 0;
AutonomousDeplState deplState;
bool stateSwitch = false;
uint32_t secsSinceBoot = 0;
while (std::getline(file, line)) {
std::istringstream iss(line);
if (lineNum == 0) {
iss >> word;
if (word.find("phase:") == string::npos) {
return false;
}
iss >> word;
if (word.find(PHASE_INIT_STR) != string::npos) {
deplState = AutonomousDeplState::INIT;
} else if (word.find(PHASE_FIRST_BURN_STR) != string::npos) {
deplState = AutonomousDeplState::FIRST_BURN;
} else if (word.find(PHASE_WAIT_STR) != string::npos) {
deplState = AutonomousDeplState::WAIT;
} else if (word.find(PHASE_SECOND_BURN_STR) != string::npos) {
deplState = AutonomousDeplState::SECOND_BURN;
} else if (word.find(PHASE_DONE) != string::npos) {
deplState = AutonomousDeplState::DONE;
} else {
return false;
}
} else if (lineNum == 1) {
iss >> word;
if (iss.bad()) {
return false;
}
if (word.find("secs_since_start:") == string::npos) {
return false;
}
iss >> secsSinceBoot;
if (iss.bad()) {
return false;
}
if (not initUptime) {
initUptime = secsSinceBoot;
}
auto switchCheck = [&](AutonomousDeplState expected) {
if (deplState != expected) {
deplState = expected;
stateSwitch = true;
}
};
if ((secsSinceBoot > FIRST_BURN_START_TIME) and (secsSinceBoot < FIRST_BURN_END_TIME)) {
switchCheck(AutonomousDeplState::FIRST_BURN);
} else if ((secsSinceBoot > WAIT_START_TIME) and (secsSinceBoot < WAIT_END_TIME)) {
switchCheck(AutonomousDeplState::WAIT);
} else if ((secsSinceBoot > SECOND_BURN_START_TIME) and
(secsSinceBoot < SECOND_BURN_END_TIME)) {
switchCheck(AutonomousDeplState::SECOND_BURN);
} else if (secsSinceBoot > SECOND_BURN_END_TIME) {
switchCheck(AutonomousDeplState::DONE);
}
}
lineNum++;
}
if (initUptime) {
secsSinceBoot = initUptime.value();
}
// Uptime has increased by X seconds so we need to update the uptime count inside the file
secsSinceBoot += Clock::getUptime().tv_sec;
if (stateSwitch or firstAutonomousCycle) {
if (deplState == AutonomousDeplState::FIRST_BURN or
deplState == AutonomousDeplState::SECOND_BURN) {
startFsmOn(config::SA_DEPL_BURN_TIME_SECS, dryRun);
} else if (deplState == AutonomousDeplState::WAIT or deplState == AutonomousDeplState::DONE or
deplState == AutonomousDeplState::INIT) {
startFsmOff();
}
}
if (deplState == AutonomousDeplState::DONE) {
remove(filename);
if (sdCard == sd::SdCard::SLOT_0) {
remove(SD_0_DEPL_FILE);
} else {
remove(SD_1_DEPL_FILE);
}
triggerEvent(AUTONOMOUS_DEPLOYMENT_COMPLETED);
} else {
if (mainSwitchCountdown.hasTimedOut()) {
std::ofstream of(filename);
of << "phase: ";
if (deplState == AutonomousDeplState::INIT) {
of << PHASE_INIT_STR << "\n";
} else if (deplState == AutonomousDeplState::FIRST_BURN) {
of << PHASE_FIRST_BURN_STR << "\n";
} else if (deplState == AutonomousDeplState::WAIT) {
of << PHASE_WAIT_STR << "\n";
} else if (deplState == AutonomousDeplState::SECOND_BURN) {
of << PHASE_SECOND_BURN_STR << "\n";
}
of << "secs_since_start: " << std::to_string(secsSinceBoot) << "\n";
}
if (firstAutonomousCycle) {
firstAutonomousCycle = false;
}
return true;
}
bool SolarArrayDeploymentHandler::checkMainPowerOn() { return checkMainPower(true); }
bool SolarArrayDeploymentHandler::checkMainPowerOff() { return checkMainPower(false); }
bool SolarArrayDeploymentHandler::checkMainPower(bool onOff) {
if ((onOff and mainLineSwitcher.getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_ON) or
(not onOff and
mainLineSwitcher.getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_OFF)) {
return true;
}
if (mainSwitchCountdown.hasTimedOut()) {
if (onOff) {
triggerEvent(MAIN_SWITCH_ON_TIMEOUT);
actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
MAIN_SWITCH_TIMEOUT_FAILURE);
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
} else {
triggerEvent(MAIN_SWITCH_OFF_TIMEOUT);
}
if (retryCounter < 3) {
if (onOff) {
stateMachine = MAIN_POWER_ON;
} else {
stateMachine = MAIN_POWER_OFF;
}
retryCounter++;
} else {
finishFsm(MAIN_SWITCH_TIMEOUT_FAILURE);
}
}
return false;
}
bool SolarArrayDeploymentHandler::startFsmOn(uint32_t burnCountdownSecs, bool dryRun) {
if (stateMachine != StateMachine::IDLE) {
return false;
}
if (burnCountdownSecs > config::SA_DEPL_MAX_BURN_TIME) {
burnCountdownSecs = config::SA_DEPL_MAX_BURN_TIME;
}
fsmInfo.dryRun = dryRun;
fsmInfo.burnCountdownMs = burnCountdownSecs * 1000;
stateMachine = StateMachine::MAIN_POWER_ON;
retryCounter = 0;
return true;
}
void SolarArrayDeploymentHandler::startFsmOff() {
if (stateMachine != StateMachine::IDLE) {
// off commands override the state machine. Cancel any active action commands.
finishFsm(returnvalue::FAILED);
}
retryCounter = 0;
stateMachine = StateMachine::MAIN_POWER_OFF;
}
void SolarArrayDeploymentHandler::finishFsm(ReturnValue_t resultForActionHelper) {
retryCounter = 0;
stateMachine = StateMachine::IDLE;
fsmInfo.dryRun = false;
fsmInfo.alternationDummy = false;
if (actionActive) {
bool success = false;
if (resultForActionHelper == returnvalue::OK or
resultForActionHelper == HasActionsIF::EXECUTION_FINISHED) {
success = true;
}
actionHelper.finish(success, rememberCommanderId, activeCmd, resultForActionHelper);
}
}
void SolarArrayDeploymentHandler::switchDeploymentTransistors() {
void SolarArrayDeploymentHandler::allOff() {
deploymentTransistorsOff();
mainLineSwitcher.sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
mainSwitchCountdown.setTimeout(mainLineSwitcher.getSwitchDelayMs());
}
bool SolarArrayDeploymentHandler::dryRunStringInFile(const char* filename) {
std::ifstream ifile(filename);
if (ifile.bad()) {
return false;
}
std::string line;
while (getline(ifile, line)) {
if (line.find("dryrun") != std::string::npos) {
return true;
}
}
return false;
}
ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result = returnvalue::OK;
result = gpioInterface->pullHigh(deplSA1);
if (actionId == DEPLOY_SOLAR_ARRAYS_MANUALLY) {
ManualDeploymentCommand cmd;
if (size < cmd.getSerializedSize()) {
return HasActionsIF::INVALID_PARAMETERS;
}
result = cmd.deSerialize(&data, &size, SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
uint32_t burnCountdown = cmd.getBurnTime();
if (not startFsmOn(burnCountdown, cmd.isDryRun())) {
return HasActionsIF::IS_BUSY;
}
actionActive = true;
rememberCommanderId = commandedBy;
return result;
} else if (actionId == SWITCH_OFF_DEPLOYMENT) {
startFsmOff();
actionActive = true;
rememberCommanderId = commandedBy;
return result;
} else {
return HasActionsIF::INVALID_ACTION_ID;
}
return result;
}
ReturnValue_t SolarArrayDeploymentHandler::saGpioAlternation() {
ReturnValue_t status = returnvalue::OK;
ReturnValue_t result;
if (channelAlternationCd.hasTimedOut() and not fsmInfo.dryRun) {
if (fsmInfo.alternationDummy) {
result = sa1Off();
if (result != returnvalue::OK) {
status = result;
}
TaskFactory::delayTask(1);
result = sa2On();
if (result != returnvalue::OK) {
status = result;
}
} else {
result = sa2Off();
if (result != returnvalue::OK) {
status = result;
}
TaskFactory::delayTask(1);
result = sa1On();
if (result != returnvalue::OK) {
status = result;
}
}
fsmInfo.alternationDummy = not fsmInfo.alternationDummy;
channelAlternationCd.resetTimer();
}
return status;
}
ReturnValue_t SolarArrayDeploymentHandler::deploymentTransistorsOff() {
ReturnValue_t status = returnvalue::OK;
ReturnValue_t result = sa1Off();
if (result != returnvalue::OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 high "
<< std::endl;
/* If gpio switch high failed, state machine is reset to wait for a command reinitiating
* the deployment sequence. */
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
status = result;
}
result = sa2Off();
if (result != returnvalue::OK) {
status = result;
}
return status;
}
ReturnValue_t SolarArrayDeploymentHandler::sa1On() {
ReturnValue_t result = gpioInterface.pullHigh(deplSA1);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 high"
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA1_GPIO_SWTICH_ON_FAILED);
actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS, SWITCHING_DEPL_SA2_FAILED);
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
}
result = gpioInterface->pullHigh(deplSA2);
if (result != returnvalue::OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 high "
<< std::endl;
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
triggerEvent(DEPL_SA2_GPIO_SWTICH_ON_FAILED);
actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS, SWITCHING_DEPL_SA2_FAILED);
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
}
deploymentCountdown.setTimeout(burnTimeMs);
stateMachine = WAIT_ON_DEPLOYMENT_FINISH;
return result;
}
void SolarArrayDeploymentHandler::handleDeploymentFinish() {
ReturnValue_t result = returnvalue::OK;
if (deploymentCountdown.hasTimedOut()) {
actionHelper.finish(true, rememberCommanderId, DEPLOY_SOLAR_ARRAYS, returnvalue::OK);
result = gpioInterface->pullLow(deplSA1);
if (result != returnvalue::OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 low "
ReturnValue_t SolarArrayDeploymentHandler::sa1Off() {
ReturnValue_t result = gpioInterface.pullLow(deplSA1);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 low"
<< std::endl;
}
result = gpioInterface->pullLow(deplSA2);
if (result != returnvalue::OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 low "
<< std::endl;
}
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
stateMachine = WAIT_FOR_MAIN_SWITCH_OFF;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA1_GPIO_SWTICH_OFF_FAILED);
}
return result;
}
ReturnValue_t SolarArrayDeploymentHandler::sa2On() {
ReturnValue_t result = gpioInterface.pullHigh(deplSA2);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 high"
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA2_GPIO_SWTICH_ON_FAILED);
}
return result;
}
ReturnValue_t SolarArrayDeploymentHandler::sa2Off() {
ReturnValue_t result = gpioInterface.pullLow(deplSA2);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 low"
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA2_GPIO_SWTICH_OFF_FAILED);
}
return result;
}
void SolarArrayDeploymentHandler::readCommandQueue() {
@ -181,27 +480,14 @@ void SolarArrayDeploymentHandler::readCommandQueue() {
}
}
ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result;
if (stateMachine != WAIT_ON_DELOYMENT_COMMAND) {
sif::error << "SolarArrayDeploymentHandler::executeAction: Received command while not in"
<< "waiting-on-command-state" << std::endl;
return DEPLOYMENT_ALREADY_EXECUTING;
}
if (actionId != DEPLOY_SOLAR_ARRAYS) {
sif::error << "SolarArrayDeploymentHandler::executeAction: Received invalid command"
<< std::endl;
result = COMMAND_NOT_SUPPORTED;
} else {
stateMachine = SWITCH_8V_ON;
rememberCommanderId = commandedBy;
result = returnvalue::OK;
}
return result;
}
MessageQueueId_t SolarArrayDeploymentHandler::getCommandQueue() const {
return commandQueue->getId();
}
ReturnValue_t SolarArrayDeploymentHandler::initialize() {
ReturnValue_t result = actionHelper.initialize(commandQueue);
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
return SystemObject::initialize();
}

View File

@ -1,19 +1,46 @@
#ifndef MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
#define MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
#include <devices/powerSwitcherList.h>
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/timemanager/Countdown.h>
#include <fsfw_hal/common/gpio/GpioIF.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <unordered_map>
#include "devices/powerSwitcherList.h"
#include "eive/definitions.h"
#include "events/subsystemIdRanges.h"
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/power/PowerSwitchIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/timemanager/Countdown.h"
#include "fsfw_hal/common/gpio/GpioIF.h"
#include "mission/memory/SdCardMountedIF.h"
#include "returnvalues/classIds.h"
enum DeploymentChannels : uint8_t { SA_1 = 1, SA_2 = 2 };
class ManualDeploymentCommand : public SerialLinkedListAdapter<SerializeIF> {
public:
ManualDeploymentCommand() { setLinks(); }
void setLinks() {
setStart(&burnTime);
burnTime.setNext(&dryRun);
}
uint32_t getBurnTime() const { return burnTime.entry; }
bool isDryRun() const { return dryRun.entry; }
private:
SerializeElement<uint32_t> burnTime;
SerializeElement<uint8_t> dryRun;
};
/**
* @brief This class is used to control the solar array deployment.
*
@ -23,8 +50,29 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
public SystemObject,
public HasActionsIF {
public:
static const DeviceCommandId_t DEPLOY_SOLAR_ARRAYS = 0x5;
//! Manual deployment of the solar arrays. Burn time and channels are supplied with TC parameters
static constexpr DeviceCommandId_t DEPLOY_SOLAR_ARRAYS_MANUALLY = 0x05;
static constexpr DeviceCommandId_t SWITCH_OFF_DEPLOYMENT = 0x06;
static constexpr uint32_t FIRST_BURN_START_TIME = config::SA_DEPL_INIT_BUFFER_SECS;
static constexpr uint32_t FIRST_BURN_END_TIME =
FIRST_BURN_START_TIME + config::SA_DEPL_BURN_TIME_SECS;
static constexpr uint32_t WAIT_START_TIME = FIRST_BURN_END_TIME;
static constexpr uint32_t WAIT_END_TIME = WAIT_START_TIME + config::SA_DEPL_WAIT_TIME_SECS;
static constexpr uint32_t SECOND_BURN_START_TIME = WAIT_END_TIME;
static constexpr uint32_t SECOND_BURN_END_TIME =
SECOND_BURN_START_TIME + config::SA_DEPL_WAIT_TIME_SECS;
static constexpr char SD_0_DEPL_FILE[] = "/mnt/sd0/conf/deployment";
static constexpr char SD_1_DEPL_FILE[] = "/mnt/sd1/conf/deployment";
static constexpr char SD_0_DEPLY_INFO[] = "/mnt/sd0/conf/deployment_info.txt";
static constexpr char SD_1_DEPLY_INFO[] = "/mnt/sd1/conf/deployment_info.txt";
static constexpr char PHASE_INIT_STR[] = "init";
static constexpr char PHASE_FIRST_BURN_STR[] = "first_burn";
static constexpr char PHASE_WAIT_STR[] = "wait";
static constexpr char PHASE_SECOND_BURN_STR[] = "second_burn";
static constexpr char PHASE_DONE[] = "done";
/**
* @brief constructor
*
@ -40,10 +88,9 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
* @param deplSA2 gpioId of the GPIO controlling the deployment 2 transistor.
* @param burnTimeMs Time duration the power will be applied to the burn wires.
*/
SolarArrayDeploymentHandler(object_id_t setObjectId, object_id_t gpioDriverId,
CookieIF* gpioCookie, object_id_t mainLineSwitcherObjectId,
pcdu::Switches mainLineSwitch, gpioId_t deplSA1, gpioId_t deplSA2,
uint32_t burnTimeMs);
SolarArrayDeploymentHandler(object_id_t setObjectId, GpioIF& gpio,
PowerSwitchIF& mainLineSwitcher, pcdu::Switches mainLineSwitch,
gpioId_t deplSA1, gpioId_t deplSA2, SdCardMountedIF& sdcMountedIF);
virtual ~SolarArrayDeploymentHandler();
@ -55,6 +102,26 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
virtual ReturnValue_t initialize() override;
private:
enum AutonomousDeplState { INIT, FIRST_BURN, WAIT, SECOND_BURN, DONE };
enum StateMachine {
IDLE,
MAIN_POWER_ON,
MAIN_POWER_OFF,
WAIT_MAIN_POWER_ON,
WAIT_MAIN_POWER_OFF,
SWITCH_DEPL_GPIOS,
BURNING
};
struct FsmInfo {
// Not required anymore
// DeploymentChannels channel;
bool dryRun;
bool alternationDummy = false;
uint32_t burnCountdownMs = config::SA_DEPL_MAX_BURN_TIME;
};
static const uint8_t INTERFACE_ID = CLASS_ID::SA_DEPL_HANDLER;
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA0);
static const ReturnValue_t DEPLOYMENT_ALREADY_EXECUTING = MAKE_RETURN_CODE(0xA1);
@ -63,23 +130,41 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
static const ReturnValue_t SWITCHING_DEPL_SA2_FAILED = MAKE_RETURN_CODE(0xA4);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SA_DEPL_HANDLER;
static const Event MAIN_SWITCH_ON_TIMEOUT = MAKE_EVENT(0, severity::LOW);
static const Event MAIN_SWITCH_OFF_TIMEOUT = MAKE_EVENT(1, severity::LOW);
static const Event DEPLOYMENT_FAILED = MAKE_EVENT(2, severity::HIGH);
static const Event DEPL_SA1_GPIO_SWTICH_ON_FAILED = MAKE_EVENT(3, severity::HIGH);
static const Event DEPL_SA2_GPIO_SWTICH_ON_FAILED = MAKE_EVENT(4, severity::HIGH);
enum StateMachine {
WAIT_ON_DELOYMENT_COMMAND,
SWITCH_8V_ON,
WAIT_ON_8V_SWITCH,
SWITCH_DEPL_GPIOS,
WAIT_ON_DEPLOYMENT_FINISH,
WAIT_FOR_MAIN_SWITCH_OFF
};
//! [EXPORT] : [COMMENT] P1: Burn duration in milliseconds, P2: Dry run flag
static constexpr Event BURN_PHASE_START = event::makeEvent(SUBSYSTEM_ID, 0, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Burn duration in milliseconds, P2: Dry run flag
static constexpr Event BURN_PHASE_DONE = event::makeEvent(SUBSYSTEM_ID, 1, severity::INFO);
static constexpr Event MAIN_SWITCH_ON_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 2, severity::LOW);
static constexpr Event MAIN_SWITCH_OFF_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 3, severity::LOW);
static constexpr Event DEPL_SA1_GPIO_SWTICH_ON_FAILED =
event::makeEvent(SUBSYSTEM_ID, 4, severity::HIGH);
static constexpr Event DEPL_SA2_GPIO_SWTICH_ON_FAILED =
event::makeEvent(SUBSYSTEM_ID, 5, severity::HIGH);
static constexpr Event DEPL_SA1_GPIO_SWTICH_OFF_FAILED =
event::makeEvent(SUBSYSTEM_ID, 6, severity::HIGH);
static constexpr Event DEPL_SA2_GPIO_SWTICH_OFF_FAILED =
event::makeEvent(SUBSYSTEM_ID, 7, severity::HIGH);
static constexpr Event AUTONOMOUS_DEPLOYMENT_COMPLETED =
event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO);
StateMachine stateMachine = WAIT_ON_DELOYMENT_COMMAND;
FsmInfo fsmInfo;
StateMachine stateMachine = IDLE;
bool actionActive = false;
bool firstAutonomousCycle = true;
ActionId_t activeCmd = HasActionsIF::INVALID_ACTION_ID;
std::optional<uint64_t> initUptime;
PeriodicOperationDivider opDivider = PeriodicOperationDivider(5);
uint8_t retryCounter = 3;
bool startFsmOn(uint32_t burnCountdownSecs, bool dryRun);
void startFsmOff();
void finishFsm(ReturnValue_t resultForActionHelper);
ReturnValue_t performAutonomousDepl(sd::SdCard sdCard, bool dryRun);
bool dryRunStringInFile(const char* filename);
bool autonomousDeplForFile(sd::SdCard sdCard, const char* filename, bool dryRun);
/**
* This countdown is used to check if the PCDU sets the 8V line on in the intended time.
*/
@ -88,7 +173,10 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
/**
* This countdown is used to wait for the burn wire being successful cut.
*/
Countdown deploymentCountdown;
Countdown burnCountdown;
Countdown channelAlternationCd =
Countdown(config::SA_DEPL_CHANNEL_ALTERNATION_INTERVAL_SECS * 1000);
/**
* The message queue id of the component commanding an action will be stored in this variable.
@ -98,36 +186,25 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
/** Size of command queue */
size_t cmdQueueSize = 20;
/** The object ID of the GPIO driver which switches the deployment transistors */
object_id_t gpioDriverId;
CookieIF* gpioCookie;
/** Object id of the object responsible to switch the 8V power input. Typically the PCDU. */
object_id_t mainLineSwitcherObjectId;
/** Switch number of the 8V power switch */
uint8_t mainLineSwitch;
GpioIF& gpioInterface;
gpioId_t deplSA1;
gpioId_t deplSA2;
GpioIF* gpioInterface = nullptr;
/** Time duration switches are active to cut the burn wire */
uint32_t burnTimeMs;
/** Queue to receive messages from other objects. */
MessageQueueIF* commandQueue = nullptr;
/**
* After initialization this pointer will hold the reference to the main line switcher object.
*/
PowerSwitchIF* mainLineSwitcher = nullptr;
PowerSwitchIF& mainLineSwitcher;
/** Switch number of the 8V power switch */
uint8_t mainLineSwitch;
SdCardMountedIF& sdcMan;
ActionHelper actionHelper;
/** Queue to receive messages from other objects. */
MessageQueueIF* commandQueue = nullptr;
void readCommandQueue();
/**
@ -139,18 +216,18 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
* @brief This function polls the 8V switch state and changes the state machine when the
* switch has been enabled.
*/
void performWaitOn8VActions();
bool checkMainPowerOn();
bool checkMainPowerOff();
bool checkMainPower(bool onOff);
/**
* @brief This functions handles the switching of the solar array deployment transistors.
*/
void switchDeploymentTransistors();
void allOff();
/**
* @brief This function performs actions to finish the deployment. Essentially switches
* are turned of after the burn time has expired.
*/
void handleDeploymentFinish();
ReturnValue_t deploymentTransistorsOff();
ReturnValue_t saGpioAlternation();
ReturnValue_t sa1On();
ReturnValue_t sa1Off();
ReturnValue_t sa2On();
ReturnValue_t sa2Off();
};
#endif /* MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ */

View File

@ -4,8 +4,10 @@
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include "devicedefinitions/SusDefinitions.h"
#include "events/subsystemIdRanges.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
#include "mission/devices/max1227.h"
#include "returnvalues/classIds.h"
/**
* @brief This is the device handler class for the SUS sensor based on the MAX1227 ADC.

View File

@ -8,6 +8,7 @@
#include "fsfw/timemanager/Countdown.h"
#include "fsfw_hal/linux/gpio/Gpio.h"
#include "mission/devices/devicedefinitions/SyrlinksDefinitions.h"
#include "returnvalues/classIds.h"
/**
* @brief This is the device handler for the syrlinks transceiver. It handles the command

View File

@ -0,0 +1 @@
target_sources(${LIB_EIVE_MISSION} PRIVATE ScexDefinitions.cpp)

View File

@ -9,23 +9,28 @@
#include <cstdint>
#include "devices/powerSwitcherList.h"
#include "p60acu_hk.h"
#include "p60acu_param.h"
#include "p60dock_hk.h"
#include "p60dock_param.h"
#include "p60pdu_hk.h"
#include "p60pdu_param.h"
#include "fsfw/platform.h"
#include "gomspaceDefines.h"
namespace GOMSPACE {
enum SpecialRequestTypes {
struct TableInfo {
uint8_t sourceTable;
uint8_t targetTable;
};
enum DeviceType { PDU, ACU, P60DOCK };
enum class SpecialRequestTypes {
DEFAULT_COM_IF,
GET_PDU_HK,
GET_PDU_CONFIG,
GET_ACU_HK,
GET_ACU_CONFIG,
GET_P60DOCK_HK,
GET_P60DOCK_CONFIG
GET_P60DOCK_CONFIG,
SAVE_TABLE,
LOAD_TABLE
};
enum CspPorts : uint8_t {
@ -53,14 +58,18 @@ static const uint8_t P60_PORT_GNDWDT_RESET = 9;
* Device commands are derived from the rparam.h of the gomspace lib..
* IDs above 50 are reserved for device specific commands.
*/
static const DeviceCommandId_t PARAM_GET = 0; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t PING = 1; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t NONE = 2; // Set when no command is pending
static const DeviceCommandId_t REBOOT = 4; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t GNDWDT_RESET = 9; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t PARAM_GET = 0; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t PARAM_SET = 255; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t REQUEST_HK_TABLE = 16; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t REQUEST_CONFIG_TABLE = 17; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t SAVE_TABLE_FILE = 18;
static const DeviceCommandId_t SAVE_TABLE_DEFAULT = 19;
static const DeviceCommandId_t LOAD_TABLE = 20;
static const DeviceCommandId_t PARAM_SET = 255; //!< [EXPORT] : [COMMAND]
// Not implemented yet
// static const DeviceCommandId_t REQUEST_CALIB_TABLE = 18; //!< [EXPORT] : [COMMAND]
//! [EXPORT] : [COMMAND] Print switch states, voltages and currents to the console
@ -199,8 +208,8 @@ static const uint16_t MAX_CONFIGTABLE_ADDRESS = 408;
static const uint16_t MAX_HKTABLE_ADDRESS = 187;
// Sources:
// GomSpace library lib/p60-dock_client/include/gs/p60-dock/param
static const uint16_t HK_TABLE_SIZE = P60DOCK_HK_SIZE;
static const uint16_t CONFIG_TABLE_SIZE = P60DOCK_PARAM_SIZE;
static const uint16_t HK_TABLE_SIZE = gsConstants::P60DOCK_HK_SIZE;
static const uint16_t CONFIG_TABLE_SIZE = gsConstants::P60DOCK_PARAM_SIZE;
static const size_t MAX_REPLY_SIZE = CONFIG_TABLE_SIZE;
static const uint16_t CAL_TABLE = 0xAE;
static const uint8_t HK_TABLE_ENTRIES = 100;
@ -376,8 +385,8 @@ enum Ids {
static const uint16_t MAX_CONFIGTABLE_ADDRESS = 316;
static const uint16_t MAX_HKTABLE_ADDRESS = 141;
/** The size of the csp reply containing the housekeeping table data */
static const uint16_t HK_TABLE_SIZE = P60PDU_HK_SIZE;
static const uint16_t CONFIG_TABLE_SIZE = P60PDU_PARAM_SIZE;
static const uint16_t HK_TABLE_SIZE = gsConstants::P60PDU_HK_SIZE;
static const uint16_t CONFIG_TABLE_SIZE = gsConstants::P60PDU_PARAM_SIZE;
/** When retrieving full configuration parameter table */
static const uint16_t MAX_REPLY_SIZE = CONFIG_TABLE_SIZE;
static const uint8_t HK_TABLE_ENTRIES = 73;
@ -645,8 +654,8 @@ enum Ids : lp_id_t {
static const uint16_t MAX_CONFIGTABLE_ADDRESS = 26;
static const uint16_t MAX_HKTABLE_ADDRESS = 120;
static const uint8_t HK_TABLE_ENTRIES = 64;
static const uint16_t HK_TABLE_SIZE = P60ACU_HK_SIZE;
static const uint16_t CONFIG_TABLE_SIZE = P60ACU_PARAM_SIZE;
static const uint16_t HK_TABLE_SIZE = gsConstants::P60ACU_HK_SIZE;
static const uint16_t CONFIG_TABLE_SIZE = gsConstants::P60ACU_PARAM_SIZE;
static const size_t MAX_REPLY_SIZE = HK_TABLE_SIZE;
class CoreHk : public StaticLocalDataSet<14> {

View File

@ -113,6 +113,8 @@ class AdisGyroPrimaryDataset : public StaticLocalDataSet<8> {
private:
friend class GyroADIS1650XHandler;
friend class GyroAdisDummy;
/** Constructor for the data creator */
AdisGyroPrimaryDataset(HasLocalDataPoolIF* hkOwner)
: StaticLocalDataSet(hkOwner, ADIS1650X::ADIS_DATASET_ID) {}

View File

@ -5,6 +5,7 @@
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include "events/subsystemIdRanges.h"
#include "objects/systemObjectList.h"
namespace RwDefinitions {

View File

@ -1,13 +0,0 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
#include <cstdint>
// Definitions for the Solar Cell Experiment
namespace scex {
static constexpr uint8_t CMD_PING = 0x4e;
}
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_ */

View File

@ -0,0 +1,35 @@
#include "ScexDefinitions.h"
#include <fsfw/globalfunctions/CRC.h>
#include <cstring>
uint8_t scex::createCmdByte(Cmds cmd, bool tempCheck) {
return (IDLE_BIT_0_DEF_STATE << 7) | (IDLE_BIT_1_DEF_STATE << 6) | (cmd << 1) | tempCheck;
}
ReturnValue_t scex::prepareScexCmd(Cmds cmd, std::pair<uint8_t*, size_t> cmdBufPair, size_t& cmdLen,
std::pair<const uint8_t*, size_t> usrDataPair, bool tempCheck) {
using namespace scex;
uint8_t* cmdBuf = cmdBufPair.first;
const uint8_t* userData = usrDataPair.first;
// Send command
if (cmdBuf == nullptr or (cmdBufPair.second < usrDataPair.second + HEADER_LEN + CRC_LEN) or
(usrDataPair.second > 0 and userData == nullptr)) {
cmdLen = 0;
return returnvalue::FAILED;
}
cmdBuf[0] = createCmdByte(cmd, tempCheck);
// These two fields are the packet counter and the total packet count. Those are 1 and 1 for each
// telecommand so far
cmdBuf[1] = 1;
cmdBuf[2] = 1;
cmdBuf[3] = (usrDataPair.second >> 8) & 0xff;
cmdBuf[4] = usrDataPair.second & 0xff;
std::memcpy(cmdBuf + HEADER_LEN, userData, usrDataPair.second);
uint16_t crc = CRC::crc16ccitt(cmdBuf, usrDataPair.second + HEADER_LEN);
cmdBuf[usrDataPair.second + HEADER_LEN] = (crc >> 8) & 0xff;
cmdBuf[usrDataPair.second + HEADER_LEN + 1] = crc & 0xff;
cmdLen = usrDataPair.second + HEADER_LEN + CRC_LEN;
return returnvalue::OK;
}

View File

@ -0,0 +1,52 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/events/Event.h>
#include <cstdint>
#include <vector>
#include "eive/eventSubsystemIds.h"
#include "eive/objects.h"
// Definitions for the Solar Cell Experiment
namespace scex {
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SCEX_HANDLER;
static constexpr Event MISSING_PACKET = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
static constexpr Event EXPERIMENT_TIMEDOUT = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW);
//! FRAM, One Cell or All cells command finished. P1: Command ID
static constexpr Event MULTI_PACKET_COMMAND_DONE =
event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO);
enum Cmds : DeviceCommandId_t {
PING = 0b00111,
ALL_CELLS_CMD = 0b00101,
ONE_CELL = 0b00110,
FRAM = 0b00001,
EXP_STATUS_CMD = 0b00010,
TEMP_CMD = 0b00011,
ION_CMD = 0b00100,
ERROR_REPLY = 0b01000,
INVALID = 255
};
static const std::vector<DeviceCommandId_t> VALID_CMDS = {
PING, ALL_CELLS_CMD, ONE_CELL, FRAM, EXP_STATUS_CMD, TEMP_CMD, ION_CMD};
static constexpr uint8_t HEADER_LEN = 5;
static constexpr uint8_t CRC_LEN = 2;
static constexpr uint8_t IDLE_BIT_0_DEF_STATE = 0;
static constexpr uint8_t IDLE_BIT_1_DEF_STATE = 1;
uint8_t createCmdByte(Cmds cmd, bool tempCheck = false);
ReturnValue_t prepareScexCmd(Cmds cmd, std::pair<uint8_t*, size_t> cmdBufPair, size_t& cmdLen,
std::pair<const uint8_t*, size_t> usrDataPair, bool tempCheck = false);
} // namespace scex
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_ */

View File

@ -39,7 +39,7 @@ class SpTcBase {
}
void updateSpFields() {
spParams.creator.setDataLen(spParams.dataFieldLen - 1);
spParams.creator.setDataLenField(spParams.dataFieldLen - 1);
spParams.creator.setPacketType(ccsds::PacketType::TC);
}

View File

@ -1,8 +1,7 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_SYRLINKSDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_SYRLINKSDEFINITIONS_H_
#include <commonSubsystemIds.h>
#include "eive/eventSubsystemIds.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
namespace syrlinks {

View File

@ -0,0 +1,33 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINES_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINES_H_
#include "fsfw/platform.h"
#ifdef PLATFORM_UNIX
// I really don't want to pull in all of those GomSpace headers just for 6 constants..
// Those are the headers which contain the defines which were just hardcoded below.
//#include "p60acu_hk.h"
//#include "p60acu_param.h"
//#include "p60dock_hk.h"
//#include "p60dock_param.h"
//#include "p60pdu_hk.h"
//#include "p60pdu_param.h"
#endif
#include <cstdint>
namespace gsConstants {
static constexpr uint32_t P60DOCK_HK_SIZE = 0xBE;
static constexpr uint32_t P60DOCK_PARAM_SIZE = 0x19C;
static constexpr uint32_t P60PDU_HK_SIZE = 0x90;
static constexpr uint32_t P60PDU_PARAM_SIZE = 0x13E;
static constexpr uint32_t P60ACU_HK_SIZE = 0x7C;
static constexpr uint32_t P60ACU_PARAM_SIZE = 0x1B;
} // namespace gsConstants
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINES_H_ */

View File

@ -1,9 +1,10 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_
#include <common/config/commonSubsystemIds.h>
#include <fsfw/events/Event.h>
#include "eive/eventSubsystemIds.h"
namespace power {
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_HANDLER;

View File

@ -2,7 +2,7 @@
#include <fstream>
#include "fsfw/memory/HasFileSystemIF.h"
#include "fsfw/filesystem/HasFileSystemIF.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
NVMParameterBase::NVMParameterBase(std::string fullName) : fullName(fullName) {}

View File

@ -6,6 +6,7 @@
#include <string>
#include "fsfw/returnvalues/returnvalue.h"
#include "returnvalues/classIds.h"
class NVMParameterBase {
public:

View File

@ -1,6 +1,7 @@
#ifndef MISSION_MEMORY_SDCARDMOUNTERIF_H_
#define MISSION_MEMORY_SDCARDMOUNTERIF_H_
#include <optional>
#include <string>
#include "definitions.h"
@ -8,11 +9,11 @@
class SdCardMountedIF {
public:
virtual ~SdCardMountedIF(){};
virtual std::string getCurrentMountPrefix() const = 0;
virtual bool isSdCardMounted(sd::SdCard sdCard) = 0;
virtual sd::SdCard getPreferredSdCard() const = 0;
virtual const std::string& getCurrentMountPrefix() const = 0;
virtual bool isSdCardUsable(sd::SdCard sdCard) = 0;
virtual std::optional<sd::SdCard> getPreferredSdCard() const = 0;
virtual void setActiveSdCard(sd::SdCard sdCard) = 0;
virtual sd::SdCard getActiveSdCard() const = 0;
virtual std::optional<sd::SdCard> getActiveSdCard() const = 0;
private:
};

View File

@ -1,6 +1,6 @@
#include "AcsBoardFdir.h"
#include <common/config/commonObjects.h>
#include "eive/objects.h"
AcsBoardFdir::AcsBoardFdir(object_id_t sensorId)
: DeviceHandlerFailureIsolation(sensorId, objects::ACS_BOARD_ASS) {}

View File

@ -1,6 +1,6 @@
#include "RtdFdir.h"
#include <common/config/commonObjects.h>
#include "eive/objects.h"
RtdFdir::RtdFdir(object_id_t sensorId)
: DeviceHandlerFailureIsolation(sensorId, objects::TCS_BOARD_ASS) {}

View File

@ -1,6 +1,6 @@
#include "SusFdir.h"
#include <common/config/commonObjects.h>
#include "eive/objects.h"
SusFdir::SusFdir(object_id_t sensorId)
: DeviceHandlerFailureIsolation(sensorId, objects::SUS_BOARD_ASS) {}

View File

@ -6,11 +6,10 @@
#include "OBSWConfig.h"
AcsBoardAssembly::AcsBoardAssembly(object_id_t objectId, object_id_t parentId,
PowerSwitchIF* switcher, AcsBoardHelper helper, GpioIF* gpioIF)
: DualLaneAssemblyBase(objectId, parentId, switcher, SWITCH_A, SWITCH_B,
POWER_STATE_MACHINE_TIMEOUT, SIDE_SWITCH_TRANSITION_NOT_ALLOWED,
TRANSITION_OTHER_SIDE_FAILED),
AcsBoardAssembly::AcsBoardAssembly(object_id_t objectId, PowerSwitchIF* switcher,
AcsBoardHelper helper, GpioIF* gpioIF)
: DualLaneAssemblyBase(objectId, switcher, SWITCH_A, SWITCH_B, POWER_STATE_MACHINE_TIMEOUT,
SIDE_SWITCH_TRANSITION_NOT_ALLOWED, TRANSITION_OTHER_SIDE_FAILED),
helper(helper),
gpioIF(gpioIF) {
if (switcher == nullptr) {
@ -275,42 +274,4 @@ void AcsBoardAssembly::refreshHelperModes() {
}
}
ReturnValue_t AcsBoardAssembly::initialize() {
ReturnValue_t result = registerChild(helper.gyro0AdisIdSideA);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.gyro1L3gIdSideA);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.gyro2AdisIdSideB);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.gyro3L3gIdSideB);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.mgm0Lis3IdSideA);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.mgm1Rm3100IdSideA);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.mgm2Lis3IdSideB);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.mgm3Rm3100IdSideB);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(helper.gpsId);
if (result != returnvalue::OK) {
return result;
}
return AssemblyBase::initialize();
}
ReturnValue_t AcsBoardAssembly::initialize() { return AssemblyBase::initialize(); }

View File

@ -1,13 +1,13 @@
#ifndef MISSION_SYSTEM_ACSBOARDASSEMBLY_H_
#define MISSION_SYSTEM_ACSBOARDASSEMBLY_H_
#include <common/config/commonSubsystemIds.h>
#include <devices/powerSwitcherList.h>
#include <fsfw/objectmanager/frameworkObjects.h>
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
#include "DualLaneAssemblyBase.h"
#include "DualLanePowerStateMachine.h"
#include "eive/eventSubsystemIds.h"
struct AcsBoardHelper {
AcsBoardHelper(object_id_t mgm0Id, object_id_t mgm1Id, object_id_t mgm2Id, object_id_t mgm3Id,
@ -94,8 +94,8 @@ class AcsBoardAssembly : public DualLaneAssemblyBase {
static constexpr uint8_t NUMBER_DEVICES_MODE_TABLE = 9;
AcsBoardAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
AcsBoardHelper helper, GpioIF* gpioIF);
AcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, AcsBoardHelper helper,
GpioIF* gpioIF);
/**
* In dual mode, the A side or the B side GPS device can be used, but not both.

View File

@ -1,5 +1,5 @@
#include "AcsSubsystem.h"
AcsSubsystem::AcsSubsystem(object_id_t setObjectId, object_id_t parent,
uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables)
: Subsystem(setObjectId, parent, maxNumberOfSequences, maxNumberOfTables) {}
AcsSubsystem::AcsSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables)
: Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables) {}

View File

@ -5,8 +5,7 @@
class AcsSubsystem : public Subsystem {
public:
AcsSubsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables);
AcsSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
private:
};

View File

@ -1,14 +1,13 @@
target_sources(${LIB_EIVE_MISSION} PRIVATE
EiveSystem.cpp
AcsSubsystem.cpp
ComSubsystem.cpp
PayloadSubsystem.cpp
AcsBoardAssembly.cpp
SusAssembly.cpp
RwAssembly.cpp
DualLanePowerStateMachine.cpp
PowerStateMachineBase.cpp
DualLaneAssemblyBase.cpp
TcsBoardAssembly.cpp
)
target_sources(
${LIB_EIVE_MISSION}
PRIVATE EiveSystem.cpp
AcsSubsystem.cpp
ComSubsystem.cpp
PayloadSubsystem.cpp
AcsBoardAssembly.cpp
SusAssembly.cpp
RwAssembly.cpp
DualLanePowerStateMachine.cpp
PowerStateMachineBase.cpp
DualLaneAssemblyBase.cpp
TcsBoardAssembly.cpp)

View File

@ -1,5 +1,5 @@
#include "ComSubsystem.h"
ComSubsystem::ComSubsystem(object_id_t setObjectId, object_id_t parent,
uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables)
: Subsystem(setObjectId, parent, maxNumberOfSequences, maxNumberOfTables) {}
ComSubsystem::ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables)
: Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables) {}

View File

@ -5,8 +5,7 @@
class ComSubsystem : public Subsystem {
public:
ComSubsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables);
ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
private:
};

View File

@ -4,12 +4,11 @@
#include "OBSWConfig.h"
DualLaneAssemblyBase::DualLaneAssemblyBase(object_id_t objectId, object_id_t parentId,
PowerSwitchIF* pwrSwitcher, pcdu::Switches switch1,
pcdu::Switches switch2, Event pwrTimeoutEvent,
Event sideSwitchNotAllowedEvent,
DualLaneAssemblyBase::DualLaneAssemblyBase(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
pcdu::Switches switch1, pcdu::Switches switch2,
Event pwrTimeoutEvent, Event sideSwitchNotAllowedEvent,
Event transitionOtherSideFailedEvent)
: AssemblyBase(objectId, parentId, 20),
: AssemblyBase(objectId, 20),
pwrStateMachine(switch1, switch2, pwrSwitcher),
pwrTimeoutEvent(pwrTimeoutEvent),
sideSwitchNotAllowedEvent(sideSwitchNotAllowedEvent),

View File

@ -18,8 +18,8 @@ class DualLaneAssemblyBase : public AssemblyBase, public ConfirmsFailuresIF {
static constexpr UniqueEventId_t POWER_STATE_MACHINE_TIMEOUT_ID = 2;
static constexpr UniqueEventId_t SIDE_SWITCH_TRANSITION_NOT_ALLOWED_ID = 3;
DualLaneAssemblyBase(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
pcdu::Switches switch1, pcdu::Switches switch2, Event pwrSwitchTimeoutEvent,
DualLaneAssemblyBase(object_id_t objectId, PowerSwitchIF* pwrSwitcher, pcdu::Switches switch1,
pcdu::Switches switch2, Event pwrSwitchTimeoutEvent,
Event sideSwitchNotAllowedEvent, Event transitionOtherSideFailedEvent);
protected:

View File

@ -1,5 +1,5 @@
#include "EiveSystem.h"
EiveSystem::EiveSystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
EiveSystem::EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables)
: Subsystem(setObjectId, parent, maxNumberOfSequences, maxNumberOfTables) {}
: Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables) {}

View File

@ -5,8 +5,7 @@
class EiveSystem : public Subsystem {
public:
EiveSystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables);
EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
private:
};

View File

@ -1,5 +1,5 @@
#include "PayloadSubsystem.h"
PayloadSubsystem::PayloadSubsystem(object_id_t setObjectId, object_id_t parent,
uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables)
: Subsystem(setObjectId, parent, maxNumberOfSequences, maxNumberOfTables) {}
PayloadSubsystem::PayloadSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables)
: Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables) {}

View File

@ -5,7 +5,7 @@
class PayloadSubsystem : public Subsystem {
public:
PayloadSubsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
PayloadSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables);
private:

View File

@ -1,8 +1,8 @@
#include "RwAssembly.h"
RwAssembly::RwAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
power::Switch_t switcher, RwHelper helper)
: AssemblyBase(objectId, parentId), helper(helper), switcher(pwrSwitcher, switcher) {
RwAssembly::RwAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switcher,
RwHelper helper)
: AssemblyBase(objectId), helper(helper), switcher(pwrSwitcher, switcher) {
ModeListEntry entry;
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
entry.setObject(helper.rwIds[idx]);
@ -167,16 +167,7 @@ bool RwAssembly::isUseable(object_id_t object, Mode_t mode) {
return false;
}
ReturnValue_t RwAssembly::initialize() {
ReturnValue_t result = returnvalue::OK;
for (const auto& obj : helper.rwIds) {
result = registerChild(obj);
if (result != returnvalue::OK) {
return result;
}
}
return SubsystemBase::initialize();
}
ReturnValue_t RwAssembly::initialize() { return SubsystemBase::initialize(); }
void RwAssembly::handleModeTransitionFailed(ReturnValue_t result) {
if (targetMode == MODE_OFF) {

View File

@ -12,8 +12,8 @@ struct RwHelper {
class RwAssembly : public AssemblyBase {
public:
RwAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
power::Switch_t switcher, RwHelper helper);
RwAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switcher,
RwHelper helper);
private:
static constexpr uint8_t NUMBER_RWS = 4;

View File

@ -4,9 +4,8 @@
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/serviceinterface.h>
SusAssembly::SusAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
SusAssHelper helper)
: DualLaneAssemblyBase(objectId, parentId, pwrSwitcher, SWITCH_NOM, SWITCH_RED,
SusAssembly::SusAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, SusAssHelper helper)
: DualLaneAssemblyBase(objectId, pwrSwitcher, SWITCH_NOM, SWITCH_RED,
POWER_STATE_MACHINE_TIMEOUT, SIDE_SWITCH_TRANSITION_NOT_ALLOWED,
TRANSITION_OTHER_SIDE_FAILED),
helper(helper),
@ -121,16 +120,7 @@ ReturnValue_t SusAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t wan
return returnvalue::OK;
}
ReturnValue_t SusAssembly::initialize() {
ReturnValue_t result = returnvalue::OK;
for (const auto& id : helper.susIds) {
result = registerChild(id);
if (result != returnvalue::OK) {
return result;
}
}
return AssemblyBase::initialize();
}
ReturnValue_t SusAssembly::initialize() { return AssemblyBase::initialize(); }
bool SusAssembly::isUseable(object_id_t object, Mode_t mode) {
if (healthHelper.healthTable->isFaulty(object)) {

View File

@ -5,6 +5,8 @@
#include <fsfw/devicehandlers/AssemblyBase.h>
#include "DualLaneAssemblyBase.h"
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
struct SusAssHelper {
public:
@ -38,8 +40,7 @@ class SusAssembly : public DualLaneAssemblyBase {
static constexpr Event SIDE_SWITCH_TRANSITION_NOT_ALLOWED =
event::makeEvent(SUBSYSTEM_ID, 3, severity::LOW);
SusAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
SusAssHelper helper);
SusAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, SusAssHelper helper);
private:
enum class States { IDLE, SWITCHING_POWER, MODE_COMMANDING } state = States::IDLE;

View File

@ -3,10 +3,9 @@
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/ipc/QueueFactory.h>
TcsBoardAssembly::TcsBoardAssembly(object_id_t objectId, object_id_t parentId,
PowerSwitchIF* pwrSwitcher, power::Switch_t theSwitch,
TcsBoardHelper helper)
: AssemblyBase(objectId, parentId, 24), switcher(pwrSwitcher, theSwitch), helper(helper) {
TcsBoardAssembly::TcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t theSwitch, TcsBoardHelper helper)
: AssemblyBase(objectId, 24), switcher(pwrSwitcher, theSwitch), helper(helper) {
eventQueue = QueueFactory::instance()->createMessageQueue(24);
ModeListEntry entry;
for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) {
@ -90,16 +89,7 @@ ReturnValue_t TcsBoardAssembly::isModeCombinationValid(Mode_t mode, Submode_t su
return HasModesIF::INVALID_MODE;
}
ReturnValue_t TcsBoardAssembly::initialize() {
ReturnValue_t result = returnvalue::OK;
for (const auto& obj : helper.rtdInfos) {
result = registerChild(obj.first);
if (result != returnvalue::OK) {
return result;
}
}
return SubsystemBase::initialize();
}
ReturnValue_t TcsBoardAssembly::initialize() { return AssemblyBase::initialize(); }
void TcsBoardAssembly::startTransition(Mode_t mode, Submode_t submode) {
if (mode != MODE_OFF) {

View File

@ -5,6 +5,9 @@
#include <fsfw/devicehandlers/AssemblyBase.h>
#include <fsfw/power/PowerSwitcher.h>
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
struct TcsBoardHelper {
TcsBoardHelper(std::array<std::pair<object_id_t, std::string>, 16> rtdInfos)
: rtdInfos(std::move(rtdInfos)) {}
@ -17,8 +20,8 @@ class TcsBoardAssembly : public AssemblyBase, public ConfirmsFailuresIF {
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_BOARD_ASS;
static constexpr Event CHILDREN_LOST_MODE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
TcsBoardAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
power::Switch_t switcher, TcsBoardHelper helper);
TcsBoardAssembly(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t switcher,
TcsBoardHelper helper);
ReturnValue_t initialize() override;

View File

@ -1,6 +1,2 @@
target_sources(${LIB_EIVE_MISSION} PRIVATE
acsModeTree.cpp
payloadModeTree.cpp
system.cpp
util.cpp
)
target_sources(${LIB_EIVE_MISSION} PRIVATE acsModeTree.cpp payloadModeTree.cpp
system.cpp util.cpp)

View File

@ -1,16 +1,22 @@
#include "acsModeTree.h"
#include <commonObjects.h>
#include <fsfw/container/FixedMap.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/modes/HasModesIF.h>
#include <fsfw/subsystem/Subsystem.h>
#include <fsfw/subsystem/modes/ModeDefinitions.h>
#include "eive/objects.h"
#include "mission/controller/controllerdefinitions/AcsControllerDefinitions.h"
#include "util.h"
// Alias for checker function
Subsystem satsystem::acs::ACS_SUBSYSTEM(objects::ACS_SUBSYSTEM, 12, 24);
namespace {
// Alias for checker function
const auto check = subsystem::checkInsert;
void checkInsert(ReturnValue_t result, const char* ctx);
void buildOffSequence(Subsystem* ss, ModeListEntry& eh);
void buildDetumbleSequence(Subsystem* ss, ModeListEntry& entryHelper);
void buildSafeSequence(Subsystem* ss, ModeListEntry& entryHelper);
@ -19,7 +25,7 @@ void buildIdleChargeSequence(Subsystem* ss, ModeListEntry& entryHelper);
void buildTargetPtSequence(Subsystem* ss, ModeListEntry& entryHelper);
} // namespace
const auto check = subsystem::checkInsert;
static const auto OFF = HasModesIF::MODE_OFF;
static const auto NML = DeviceHandlerIF::MODE_NORMAL;
@ -69,7 +75,7 @@ auto ACS_TABLE_IDLE_CHRG_TRANS_1 = std::make_pair(
auto ACS_SEQUENCE_TARGET_PT =
std::make_pair(acs::CtrlModes::TARGET_PT, FixedArrayList<ModeListEntry, 3>());
auto ACS_TABLE_TARGET_PT_TGT =
std::make_pair((acs::CtrlModes::TARGET_PT << 24) | 1, FixedArrayList<ModeListEntry, 5>());
std::make_pair((acs::CtrlModes::TARGET_PT << 24) | 1, FixedArrayList<ModeListEntry, 6>());
auto ACS_TABLE_TARGET_PT_TRANS_0 =
std::make_pair((acs::CtrlModes::TARGET_PT << 24) | 2, FixedArrayList<ModeListEntry, 5>());
auto ACS_TABLE_TARGET_PT_TRANS_1 =
@ -77,14 +83,13 @@ auto ACS_TABLE_TARGET_PT_TRANS_1 =
void satsystem::acs::init() {
ModeListEntry entry;
Subsystem* acsSubsystem = new Subsystem(objects::ACS_SUBSYSTEM, objects::EIVE_SYSTEM, 12, 24);
buildOffSequence(acsSubsystem, entry);
buildSafeSequence(acsSubsystem, entry);
buildDetumbleSequence(acsSubsystem, entry);
buildIdleSequence(acsSubsystem, entry);
buildIdleChargeSequence(acsSubsystem, entry);
buildTargetPtSequence(acsSubsystem, entry);
acsSubsystem->setInitialMode(OFF);
buildOffSequence(&ACS_SUBSYSTEM, entry);
buildSafeSequence(&ACS_SUBSYSTEM, entry);
buildDetumbleSequence(&ACS_SUBSYSTEM, entry);
buildIdleSequence(&ACS_SUBSYSTEM, entry);
buildIdleChargeSequence(&ACS_SUBSYSTEM, entry);
buildTargetPtSequence(&ACS_SUBSYSTEM, entry);
ACS_SUBSYSTEM.setInitialMode(HasModesIF::MODE_OFF);
}
namespace {
@ -152,7 +157,7 @@ void buildSafeSequence(Subsystem* ss, ModeListEntry& eh) {
iht(objects::IMTQ_HANDLER, NML, 0, ACS_TABLE_SAFE_TGT.second);
iht(objects::SUS_BOARD_ASS, NML, 0, ACS_TABLE_SAFE_TGT.second);
iht(objects::ACS_BOARD_ASS, NML, 0, ACS_TABLE_SAFE_TGT.second);
check(ss->addTable(&ACS_TABLE_SAFE_TGT.second, ACS_TABLE_OFF_TGT.first, false, true), ctxc);
check(ss->addTable(&ACS_TABLE_SAFE_TGT.second, ACS_TABLE_SAFE_TGT.first, false, true), ctxc);
// Build SAFE transition 0
iht(objects::IMTQ_HANDLER, NML, 0, ACS_TABLE_SAFE_TRANS_0.second);
@ -172,7 +177,7 @@ void buildSafeSequence(Subsystem* ss, ModeListEntry& eh) {
ihs(ACS_SEQUENCE_SAFE.second, ACS_TABLE_SAFE_TGT.first, 0, true);
ihs(ACS_SEQUENCE_SAFE.second, ACS_TABLE_SAFE_TRANS_0.first, 0, false);
ihs(ACS_SEQUENCE_SAFE.second, ACS_TABLE_SAFE_TRANS_1.first, 0, false);
check(ss->addSequence(&ACS_SEQUENCE_SAFE.second, ACS_SEQUENCE_SAFE.first, ACS_SEQUENCE_OFF.first,
check(ss->addSequence(&ACS_SEQUENCE_SAFE.second, ACS_SEQUENCE_SAFE.first, ACS_SEQUENCE_SAFE.first,
false, true),
ctxc);
}
@ -385,4 +390,17 @@ void buildTargetPtSequence(Subsystem* ss, ModeListEntry& eh) {
ctxc);
}
void checkInsert(ReturnValue_t result, const char* ctx) {
if (result != returnvalue::OK) {
sif::warning << "satsystem::checkInsert: Insertion failed at " << ctx;
if (result == mapdefs::KEY_ALREADY_EXISTS) {
sif::warning << ": Key already exists" << std::endl;
} else if (result == mapdefs::MAP_FULL) {
sif::warning << ": Map full" << std::endl;
} else {
sif::warning << std::endl;
}
}
}
} // namespace

View File

@ -5,7 +5,8 @@ class Subsystem;
namespace satsystem {
namespace acs {
extern Subsystem ACS_SUBSYSTEM;
void init();
}
} // namespace acs
} // namespace satsystem

View File

@ -1,6 +1,6 @@
#include "payloadModeTree.h"
#include <commonObjects.h>
#include "eive/objects.h"
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/modes/HasModesIF.h>
#include <fsfw/retval.h>
@ -74,7 +74,7 @@ auto PL_TABLE_SCEX_TRANS_0 =
void satsystem::pl::init() {
ModeListEntry entry;
Subsystem* plSubsystem = new Subsystem(objects::PL_SUBSYSTEM, objects::EIVE_SYSTEM, 12, 24);
Subsystem* plSubsystem = new Subsystem(objects::PL_SUBSYSTEM, 12, 24);
initOffSequence(plSubsystem, entry);
initPlMpsocStreamSequence(plSubsystem, entry);
initPlCamStreamSequence(plSubsystem, entry);
@ -112,7 +112,7 @@ void initOffSequence(Subsystem* ss, ModeListEntry& eh) {
// Build OFF transition 0
iht(objects::PLOC_SWITCHER, OFF, 0, PL_TABLE_OFF_TRANS.second);
iht(objects::CAM_SWITCHER, OFF, 0, PL_TABLE_OFF_TRANS.second);
iht(objects::SCEX_HANDLER, OFF, 0, PL_TABLE_OFF_TRANS.second);
iht(objects::SCEX, OFF, 0, PL_TABLE_OFF_TRANS.second);
iht(objects::PLPCDU_HANDLER, OFF, 0, PL_TABLE_OFF_TRANS.second);
iht(objects::PLOC_SUBSYSTEM, OFF, 0, PL_TABLE_OFF_TRANS.second);
check(ss->addTable(TableEntry(PL_TABLE_OFF_TRANS.first, &PL_TABLE_OFF_TRANS.second)), ctxc);
@ -158,7 +158,7 @@ void initPlMpsocStreamSequence(Subsystem* ss, ModeListEntry& eh) {
// Build MPSoC stream transition 0
iht(objects::PLOC_SWITCHER, ON, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
iht(objects::CAM_SWITCHER, OFF, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
iht(objects::SCEX_HANDLER, OFF, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
iht(objects::SCEX, OFF, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
check(ss->addTable(
TableEntry(PL_TABLE_MPSOC_STREAM_TRANS_0.first, &PL_TABLE_MPSOC_STREAM_TRANS_0.second)),
ctxc);
@ -209,7 +209,7 @@ void initPlCamStreamSequence(Subsystem* ss, ModeListEntry& eh) {
// PLOC is actively commanded off here
iht(objects::PLOC_SUBSYSTEM, OFF, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
iht(objects::CAM_SWITCHER, ON, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
iht(objects::SCEX_HANDLER, OFF, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
iht(objects::SCEX, OFF, 0, PL_TABLE_MPSOC_STREAM_TRANS_0.second);
check(ss->addTable(
TableEntry(PL_TABLE_MPSOC_STREAM_TRANS_0.first, &PL_TABLE_MPSOC_STREAM_TRANS_0.second)),
ctxc);
@ -345,12 +345,12 @@ void initScexSequence(Subsystem* ss, ModeListEntry& eh) {
};
// Build SCEX target
iht(objects::SCEX_HANDLER, NML, 0, PL_TABLE_SCEX_TGT.second);
iht(objects::SCEX, NML, 0, PL_TABLE_SCEX_TGT.second);
check(ss->addTable(TableEntry(PL_TABLE_EARTH_OBSV_TGT.first, &PL_TABLE_EARTH_OBSV_TGT.second)),
ctxc);
// Build SCEX transition 0
iht(objects::SCEX_HANDLER, NML, 0, PL_TABLE_SCEX_TGT.second);
iht(objects::SCEX, NML, 0, PL_TABLE_SCEX_TGT.second);
check(ss->addTable(TableEntry(PL_TABLE_SCEX_TRANS_0.first, &PL_TABLE_SCEX_TRANS_0.second)), ctxc);
// Build SCEX sequence

View File

@ -203,9 +203,9 @@ ReturnValue_t CCSDSHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentif
return returnvalue::OK;
}
uint16_t CCSDSHandler::getIdentifier() { return 0; }
uint32_t CCSDSHandler::getIdentifier() const { return 0; }
MessageQueueId_t CCSDSHandler::getRequestQueue() {
MessageQueueId_t CCSDSHandler::getRequestQueue() const {
// Forward packets directly to TC distributor
return tcDistributorQueueId;
}
@ -345,3 +345,5 @@ void CCSDSHandler::disableTransmit() {
forwardLinkstate();
transmitterCountdown.setTimeout(0);
}
const char* CCSDSHandler::getName() const { return "CCSDS Handler"; }

View File

@ -72,8 +72,9 @@ class CCSDSHandler : public SystemObject,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex);
uint16_t getIdentifier() override;
MessageQueueId_t getRequestQueue() override;
uint32_t getIdentifier() const override;
MessageQueueId_t getRequestQueue() const override;
const char* getName() const override;
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);

View File

@ -121,3 +121,5 @@ ReturnValue_t TmFunnel::initialize() {
return SystemObject::initialize();
}
const char* TmFunnel::getName() const { return "TM Funnel"; }

View File

@ -28,9 +28,10 @@ class TmFunnel : public AcceptsTelemetryIF, public ExecutableObjectIF, public Sy
uint8_t reportReceptionVc = 0);
virtual ~TmFunnel();
virtual MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) override;
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
virtual ReturnValue_t initialize() override;
const char* getName() const override;
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) override;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t initialize() override;
protected:
static object_id_t downlinkDestination;

View File

@ -12,6 +12,7 @@ VirtualChannel::VirtualChannel(uint8_t vcId, uint32_t tmQueueDepth, object_id_t
auto mqArgs = MqArgs(ownerId, reinterpret_cast<void*>(vcId));
tmQueue = QueueFactory::instance()->createMessageQueue(
tmQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
vcName = "VC " + vcId;
}
ReturnValue_t VirtualChannel::initialize() {
@ -65,3 +66,5 @@ void VirtualChannel::setPtmeObject(PtmeIF* ptme_) {
}
void VirtualChannel::setLinkState(bool linkIsUp_) { linkIsUp = linkIsUp_; }
const char* VirtualChannel::getName() const { return vcName.c_str(); }

View File

@ -42,11 +42,13 @@ class VirtualChannel : public AcceptsTelemetryIF {
* to ground station is down.
*/
void setLinkState(bool linkIsUp_);
const char* getName() const override;
private:
PtmeIF* ptme = nullptr;
MessageQueueIF* tmQueue = nullptr;
uint8_t vcId = 0;
std::string vcName;
bool linkIsUp = false;

View File

@ -1,2 +1,3 @@
target_sources(${LIB_EIVE_MISSION} PRIVATE Timestamp.cpp ProgressPrinter.cpp
Filenaming.cpp)
target_sources(
${LIB_EIVE_MISSION} PRIVATE Timestamp.cpp ProgressPrinter.cpp Filenaming.cpp
GlobalConfigHandler.cpp)

View File

@ -0,0 +1,20 @@
/*
* GlobalConfigFileDefinitions.h
*
* Created on: July 05, 2022
* Author: Jona Petri (IRS)
*/
#ifndef MISSION_UTILITY_GLOBALCONFIGFILEDEFINITIONS_H_
#define MISSION_UTILITY_GLOBALCONFIGFILEDEFINITIONS_H_
static constexpr double PARAM0_DEFAULT = 5.0;
static constexpr int PARAM1_DEFAULT = 905;
enum ParamIds : uint8_t {
PARAM0 = 0,
PARAM1 = 1,
PARAM2 = 2,
};
#endif /* MISSION_UTILITY_GLOBALCONFIGFILEDEFINITIONS_H_ */

View File

@ -0,0 +1,269 @@
/*
* GlobalConfigHandler.cpp
*
* Created on: May 3, 2022
* Author: Jona Petri (IRS)
*/
#include "GlobalConfigHandler.h"
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/MutexFactory.h>
#include <fsfw/ipc/QueueFactory.h>
#include "fsfw/serviceinterface/ServiceInterface.h"
MutexIF* GlobalConfigHandler::CONFIG_LOCK = nullptr;
GlobalConfigHandler::GlobalConfigHandler(object_id_t objectId, std::string configFilePath)
: SystemObject(objectId),
NVMParameterBase(configFilePath),
commandQueue(QueueFactory::instance()->createMessageQueue(20)) {
if (CONFIG_LOCK == nullptr) {
CONFIG_LOCK = MutexFactory::instance()->createMutex();
}
}
ReturnValue_t GlobalConfigHandler::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::initialize: SystemObject::initialize() failed with "
<< result << std::endl;
#endif
return result;
}
result = ReadConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::initialize: Creating JSON file at " << getFullName()
<< std::endl;
#endif
result = ResetConfigFile();
if (result != returnvalue::OK) {
return result;
}
}
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::initialize success " << std::endl;
#endif
return result;
}
GlobalConfigHandler::~GlobalConfigHandler() {}
ReturnValue_t GlobalConfigHandler::performOperation(uint8_t operationCode) {
ReturnValue_t result = returnvalue::OK;
sif::debug << "GlobalConfigHandler::performOperation" << std::endl;
return result;
}
ReturnValue_t GlobalConfigHandler::lockConfigFile() {
ReturnValue_t result = returnvalue::OK;
result = CONFIG_LOCK->lockMutex(MutexIF::TimeoutType::WAITING, 10);
return result;
}
ReturnValue_t GlobalConfigHandler::unlockConfigFile() {
ReturnValue_t result = returnvalue::OK;
result = CONFIG_LOCK->unlockMutex();
return result;
}
template <typename T>
ReturnValue_t GlobalConfigHandler::setConfigFileValue(ParamIds paramID, T data) {
ReturnValue_t result = returnvalue::OK;
ReturnValue_t resultSet = returnvalue::OK;
result = lockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::setConfigFileValue lock mutex failed with " << result
<< std::endl;
#endif
return result;
}
std::string paramString;
paramString = PARAM_KEY_MAP[paramID];
// Check if key exists in map before setting value. No check is done in setValue! Somehow
// PARAM_KEY_MAP.count(paramID) == 0 does not work
if (paramString.empty() == true) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::setConfigFileValue ParamId " << PARAM_KEY_MAP[paramID]
<< " not found!" << std::endl;
#endif
triggerEvent(SET_CONFIGFILEVALUE_FAILED, 1, 0);
return returnvalue::FAILED;
}
resultSet = setValue(PARAM_KEY_MAP[paramID], data);
if (resultSet != returnvalue::OK) {
triggerEvent(SET_CONFIGFILEVALUE_FAILED, 0, 0);
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::setConfigFileValue set json failed with " << resultSet
<< std::endl;
#endif
}
result = unlockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::setConfigFileValue unlock mutex failed with " << result
<< std::endl;
#endif
return result;
}
return resultSet;
}
template <typename T>
ReturnValue_t GlobalConfigHandler::getConfigFileValue(ParamIds paramID, T& data) {
ReturnValue_t result = returnvalue::OK;
ReturnValue_t resultGet = returnvalue::OK;
result = lockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::getConfigFileValue lock mutex failed with " << result
<< std::endl;
#endif
return result;
}
resultGet = getValue(PARAM_KEY_MAP[paramID], data);
if (resultGet != returnvalue::OK) {
triggerEvent(GET_CONFIGFILEVALUE_FAILED, 0, 0);
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::getConfigFileValue getValue failed with " << resultGet
<< std::endl;
#endif
}
result = unlockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::getConfigFileValue unlock mutex failed with " << result
<< std::endl;
#endif
return result;
}
return resultGet;
}
ReturnValue_t GlobalConfigHandler::resetConfigFileValues() {
ReturnValue_t result = returnvalue::OK;
result = lockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::resetConfigFileValues lock mutex failed with " << result
<< std::endl;
#endif
return result;
}
insertValue(PARAM_KEY_MAP[PARAM0], PARAM0_DEFAULT);
insertValue(PARAM_KEY_MAP[PARAM1], PARAM1_DEFAULT);
result = unlockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::resetConfigFileValues unlock mutex failed with " << result
<< std::endl;
#endif
return result;
}
return result;
}
ReturnValue_t GlobalConfigHandler::WriteConfigFile() {
ReturnValue_t result = returnvalue::OK;
ReturnValue_t resultWrite = returnvalue::OK;
result = lockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::WriteConfigFile lock mutex failed with " << result
<< std::endl;
#endif
return result;
}
resultWrite = writeJsonFile();
if (resultWrite != returnvalue::OK) {
triggerEvent(WRITE_CONFIGFILE_FAILED, 0, 0);
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::WriteConfigFile write json failed with " << resultWrite
<< std::endl;
#endif
}
result = unlockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::WriteConfigFile unlock mutex failed with " << result
<< std::endl;
#endif
return result;
}
return resultWrite;
}
ReturnValue_t GlobalConfigHandler::ReadConfigFile() {
ReturnValue_t result = returnvalue::OK;
ReturnValue_t resultRead = returnvalue::OK;
result = lockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::ReadConfigFile lock mutex failed with " << result
<< std::endl;
#endif
return result;
}
resultRead = readJsonFile();
if (resultRead != returnvalue::OK) {
triggerEvent(READ_CONFIGFILE_FAILED, 0, 0);
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::ReadConfigFile read json failed with " << resultRead
<< std::endl;
#endif
}
result = unlockConfigFile();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::ReadConfigFile unlock mutex failed with " << result
<< std::endl;
#endif
return result;
}
return resultRead;
}
ReturnValue_t GlobalConfigHandler::ResetConfigFile() {
ReturnValue_t result = returnvalue::OK;
result = resetConfigFileValues();
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "GlobalConfigHandler::ResetConfigFile failed with " << result << std::endl;
#endif
return result;
}
result = writeJsonFile();
return result;
}
ReturnValue_t GlobalConfigHandler::setConfigFileName(std::string configFileName) {
ReturnValue_t result = returnvalue::OK;
setFullName(configFileName);
result = ResetConfigFile();
return result;
}
std::string GlobalConfigHandler::getConfigFileName() { return getFullName(); }
template ReturnValue_t GlobalConfigHandler::getConfigFileValue<double>(ParamIds paramID,
double& data);
template ReturnValue_t GlobalConfigHandler::getConfigFileValue<int32_t>(ParamIds paramID,
int32_t& data);
template ReturnValue_t GlobalConfigHandler::setConfigFileValue<double>(ParamIds paramID,
double data);
template ReturnValue_t GlobalConfigHandler::setConfigFileValue<int32_t>(ParamIds paramID,
int32_t data);

View File

@ -0,0 +1,79 @@
/*
* GlobalConfigHandler.h
*
* Created on: May 3, 2022
* Author: Jona Petri (IRS)
*/
#ifndef MISSION_UTILITY_GLOBALCONFIGHANDLER_H_
#define MISSION_UTILITY_GLOBALCONFIGHANDLER_H_
#include <fsfw/action/ActionHelper.h>
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/storagemanager/StorageManagerIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <sstream>
#include <string>
#include "GlobalConfigFileDefinitions.h"
#include "OBSWConfig.h"
#include "fsfw/parameters/HasParametersIF.h"
#include "fsfw/parameters/ParameterHelper.h"
#include "mission/memory/NVMParameterBase.h"
static std::map<ParamIds, std::string> PARAM_KEY_MAP = {
{PARAM0, "Parameter0"},
{PARAM1, "Parameter1"},
};
/*
* Idea: This class is intended to be used as a subclass for the Core Controller.
* Its tasks is managing a configuration JSON file containing config values important for various
* object. If some function to read or write a config value is called, a mutex should be used so
* only one call is done at a time.
*/
class GlobalConfigHandler : public SystemObject,
public ExecutableObjectIF,
public NVMParameterBase {
public:
GlobalConfigHandler(object_id_t objectId, std::string configFilePath);
virtual ~GlobalConfigHandler();
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CONFIGHANDLER;
static constexpr Event SET_CONFIGFILEVALUE_FAILED = MAKE_EVENT(1, severity::MEDIUM);
static constexpr Event GET_CONFIGFILEVALUE_FAILED = MAKE_EVENT(2, severity::MEDIUM);
static constexpr Event INSERT_CONFIGFILEVALUE_FAILED = MAKE_EVENT(3, severity::MEDIUM);
static constexpr Event WRITE_CONFIGFILE_FAILED = MAKE_EVENT(4, severity::MEDIUM);
static constexpr Event READ_CONFIGFILE_FAILED = MAKE_EVENT(5, severity::MEDIUM);
ReturnValue_t performOperation(uint8_t operationCode);
ReturnValue_t initialize();
template <typename T>
ReturnValue_t setConfigFileValue(ParamIds paramID, T data);
template <typename T>
ReturnValue_t getConfigFileValue(ParamIds paramID, T& data);
ReturnValue_t ResetConfigFile();
ReturnValue_t WriteConfigFile();
std::string getConfigFileName();
private:
static MutexIF* CONFIG_LOCK;
ReturnValue_t lockConfigFile();
ReturnValue_t unlockConfigFile();
ReturnValue_t resetConfigFileValues();
ReturnValue_t setConfigFileName(std::string configFileName);
ReturnValue_t ReadConfigFile();
MessageQueueIF* commandQueue;
};
#endif /* MISSION_UTILITY_GLOBALCONFIGHANDLER_H_ */

View File

@ -1,12 +1,11 @@
#ifndef MISSION_UTILITY_INITMISSION_H_
#define MISSION_UTILITY_INITMISSION_H_
#pragma once
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
namespace initmission {
void printAddObjectError(const char* name, object_id_t objectId) {
static void printAddObjectError(const char* name, object_id_t objectId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "InitMission::printAddError: Adding object " << name << " with object ID 0x"
<< std::hex << std::setfill('0') << std::setw(8) << objectId << " failed!" << std::dec
@ -18,5 +17,3 @@ void printAddObjectError(const char* name, object_id_t objectId) {
}
} // namespace initmission
#endif /* MISSION_UTILITY_INITMISSION_H_ */