diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d03d170..28bbfd39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -461,8 +461,8 @@ if(TGT_BSP MATCHES "arm/q7s") target_link_libraries(${LIB_EIVE_MISSION} PUBLIC ${LIB_GPS} ${LIB_ARCSEC}) endif() -target_link_libraries( - ${UNITTEST_NAME} PRIVATE Catch2 ${LIB_EIVE_MISSION} rapidcsv ${LIB_DUMMIES}) +target_link_libraries(${UNITTEST_NAME} PRIVATE Catch2 ${LIB_EIVE_MISSION} + rapidcsv ${LIB_DUMMIES}) if(TGT_BSP MATCHES "arm/egse") target_link_libraries(${OBSW_NAME} PRIVATE ${LIB_ARCSEC}) diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp index 531b0b87..a9c46ec5 100644 --- a/bsp_hosted/ObjectFactory.cpp +++ b/bsp_hosted/ObjectFactory.cpp @@ -44,7 +44,11 @@ #include #include +<<<<<<< HEAD #include "dummies/helpers.h" +======= +#include "mission/utility/GlobalConfigHandler.h" +>>>>>>> origin/develop void Factory::setStaticFrameworkObjectIds() { PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR; @@ -69,6 +73,5 @@ void ObjectFactory::produce(void* args) { new TemperatureSensorsDummy(); new SusDummy(); new ThermalController(objects::THERMAL_CONTROLLER, objects::NO_OBJECT); - - // new TestTask(objects::TEST_TASK); + new TestTask(objects::TEST_TASK); } diff --git a/bsp_hosted/main.cpp b/bsp_hosted/main.cpp index 24800919..e493c1c9 100644 --- a/bsp_hosted/main.cpp +++ b/bsp_hosted/main.cpp @@ -31,6 +31,9 @@ int main(void) { << "v" << common::OBSW_VERSION << " | FSFW v" << fsfw::FSFW_VERSION << " --" << std::endl; std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; + std::cout << "-- " + << " BSP HOSTED" + << " --" << std::endl; initmission::initMission(); diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index ca63bb90..24286d5c 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1872,11 +1872,11 @@ ReturnValue_t CoreController::executeSwUpdate(SwUpdateSources sourceDir, const u sourceStr = "tmp directory"; } bool sameChipAndCopy = false; - if(chip == CURRENT_CHIP and copy == CURRENT_COPY) { + if (chip == CURRENT_CHIP and copy == CURRENT_COPY) { // This is problematic if the OBSW is running as a systemd service. // Do not allow for now. return HasActionsIF::INVALID_PARAMETERS; - //sameChipAndCopy = true; + // sameChipAndCopy = true; } sif::info << "Executing SW update for Chip " << static_cast(data[0]) << " Copy " << static_cast(data[1]) << " from " << sourceStr << std::endl; @@ -1912,7 +1912,7 @@ ReturnValue_t CoreController::executeSwUpdate(SwUpdateSources sourceDir, const u cmd.clear(); path obswDestPath; path obswVersionDestPath; - if(not sameChipAndCopy) { + if (not sameChipAndCopy) { cmd << "xsc_mount_copy " << std::to_string(data[0]) << " " << std::to_string(data[1]); result = system(cmd.str().c_str()); if (result != 0) { diff --git a/common/config/eive/eventSubsystemIds.h b/common/config/eive/eventSubsystemIds.h index 001f6d50..55c55e88 100644 --- a/common/config/eive/eventSubsystemIds.h +++ b/common/config/eive/eventSubsystemIds.h @@ -4,6 +4,7 @@ #include namespace SUBSYSTEM_ID { + enum : uint8_t { COMMON_SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE, ACS_SUBSYSTEM = 112, @@ -32,7 +33,9 @@ enum : uint8_t { ACU_HANDLER = 135, PLOC_SUPV_HELPER = 136, SYRLINKS = 137, + CONFIGHANDLER = 138, COMMON_SUBSYSTEM_ID_END + }; } diff --git a/common/config/eive/objects.h b/common/config/eive/objects.h index 75f301b0..fc245536 100644 --- a/common/config/eive/objects.h +++ b/common/config/eive/objects.h @@ -20,6 +20,7 @@ enum commonObjects : uint32_t { THERMAL_CONTROLLER = 0x43400001, ACS_CONTROLLER = 0x43000002, CORE_CONTROLLER = 0x43000003, + GLOBAL_JSON_CFG = 0x43000006, /* 0x44 ('D') for device handlers */ MGM_0_LIS3_HANDLER = 0x44120006, diff --git a/fsfw b/fsfw index c47bed07..692be9df 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit c47bed07606548fd2510caa45bdd9fc867732065 +Subproject commit 692be9df8d06beb3bfc83aad77cefd727d8f7c35 diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 17361ebb..415d150a 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -216,3 +216,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 13701;0x3585;REBOOT_SW;MEDIUM; Software reboot occurred. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h 13702;0x3586;REBOOT_MECHANISM_TRIGGERED;MEDIUM;The reboot mechanism was triggered. P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, P2: Each byte is the respective reboot count for the slots;bsp_q7s/core/CoreController.h 13703;0x3587;REBOOT_HW;MEDIUM;;bsp_q7s/core/CoreController.h +13801;0x35e9;SET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h +13802;0x35ea;GET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h +13803;0x35eb;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h +13804;0x35ec;WRITE_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h +13805;0x35ed;READ_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index 924ae0a0..68d56760 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -1,6 +1,7 @@ 0x00005060;P60DOCK_TEST_TASK 0x43000002;ACS_CONTROLLER 0x43000003;CORE_CONTROLLER +0x43000006;GLOBAL_JSON_CFG 0x43400001;THERMAL_CONTROLLER 0x44120006;MGM_0_LIS3_HANDLER 0x44120010;GYRO_0_ADIS_HANDLER diff --git a/generators/bsp_q7s_returnvalues.csv b/generators/bsp_q7s_returnvalues.csv index f464a439..7fccee95 100644 --- a/generators/bsp_q7s_returnvalues.csv +++ b/generators/bsp_q7s_returnvalues.csv @@ -419,8 +419,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x2403;MT_NoMatch;;3;MATCH_TREE_CLASS;fsfw/src/fsfw/globalfunctions/matching/MatchTree.h 0x2404;MT_Full;;4;MATCH_TREE_CLASS;fsfw/src/fsfw/globalfunctions/matching/MatchTree.h 0x2405;MT_NewNodeCreated;;5;MATCH_TREE_CLASS;fsfw/src/fsfw/globalfunctions/matching/MatchTree.h -0x3f01;DLEE_StreamTooShort;;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h -0x3f02;DLEE_DecodingError;;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h +0x3f01;DLEE_NoPacketFound;;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.h +0x3f02;DLEE_PossiblePacketLoss;;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.h 0x2f01;ASC_TooLongForTargetType;;1;ASCII_CONVERTER;fsfw/src/fsfw/globalfunctions/AsciiConverter.h 0x2f02;ASC_InvalidCharacters;;2;ASCII_CONVERTER;fsfw/src/fsfw/globalfunctions/AsciiConverter.h 0x2f03;ASC_BufferTooSmall;;3;ASCII_CONVERTER;fsfw/src/fsfw/globalfunctions/AsciiConverter.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 3983fd3c..d26a338a 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 217 translations. + * @brief Auto-generated event translation file. Contains 222 translations. * @details - * Generated on: 2022-09-29 14:08:49 + * Generated on: 2022-10-10 10:15:22 */ #include "translateEvents.h" @@ -218,6 +218,11 @@ const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE"; const char *REBOOT_SW_STRING = "REBOOT_SW"; const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED"; const char *REBOOT_HW_STRING = "REBOOT_HW"; +const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED"; +const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED"; +const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED"; +const char *WRITE_CONFIGFILE_FAILED_STRING = "WRITE_CONFIGFILE_FAILED"; +const char *READ_CONFIGFILE_FAILED_STRING = "READ_CONFIGFILE_FAILED"; const char *translateEvents(Event event) { switch ((event & 0xFFFF)) { @@ -647,6 +652,16 @@ const char *translateEvents(Event event) { return REBOOT_MECHANISM_TRIGGERED_STRING; case (13703): return REBOOT_HW_STRING; + case (13801): + return SET_CONFIGFILEVALUE_FAILED_STRING; + case (13802): + return GET_CONFIGFILEVALUE_FAILED_STRING; + case (13803): + return INSERT_CONFIGFILEVALUE_FAILED_STRING; + case (13804): + return WRITE_CONFIGFILE_FAILED_STRING; + case (13805): + return READ_CONFIGFILE_FAILED_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index d125a2a9..4535f74f 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -1,14 +1,15 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 135 translations. - * Generated on: 2022-09-29 14:08:49 + * Contains 136 translations. + * Generated on: 2022-10-10 10:15:22 */ #include "translateObjects.h" const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK"; const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; +const char *GLOBAL_JSON_CFG_STRING = "GLOBAL_JSON_CFG"; const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; @@ -150,6 +151,8 @@ const char *translateObject(object_id_t object) { return ACS_CONTROLLER_STRING; case 0x43000003: return CORE_CONTROLLER_STRING; + case 0x43000006: + return GLOBAL_JSON_CFG_STRING; case 0x43400001: return THERMAL_CONTROLLER_STRING; case 0x44120006: diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 3983fd3c..d26a338a 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 217 translations. + * @brief Auto-generated event translation file. Contains 222 translations. * @details - * Generated on: 2022-09-29 14:08:49 + * Generated on: 2022-10-10 10:15:22 */ #include "translateEvents.h" @@ -218,6 +218,11 @@ const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE"; const char *REBOOT_SW_STRING = "REBOOT_SW"; const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED"; const char *REBOOT_HW_STRING = "REBOOT_HW"; +const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED"; +const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED"; +const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED"; +const char *WRITE_CONFIGFILE_FAILED_STRING = "WRITE_CONFIGFILE_FAILED"; +const char *READ_CONFIGFILE_FAILED_STRING = "READ_CONFIGFILE_FAILED"; const char *translateEvents(Event event) { switch ((event & 0xFFFF)) { @@ -647,6 +652,16 @@ const char *translateEvents(Event event) { return REBOOT_MECHANISM_TRIGGERED_STRING; case (13703): return REBOOT_HW_STRING; + case (13801): + return SET_CONFIGFILEVALUE_FAILED_STRING; + case (13802): + return GET_CONFIGFILEVALUE_FAILED_STRING; + case (13803): + return INSERT_CONFIGFILEVALUE_FAILED_STRING; + case (13804): + return WRITE_CONFIGFILE_FAILED_STRING; + case (13805): + return READ_CONFIGFILE_FAILED_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index d125a2a9..4535f74f 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -1,14 +1,15 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 135 translations. - * Generated on: 2022-09-29 14:08:49 + * Contains 136 translations. + * Generated on: 2022-10-10 10:15:22 */ #include "translateObjects.h" const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK"; const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; +const char *GLOBAL_JSON_CFG_STRING = "GLOBAL_JSON_CFG"; const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; @@ -150,6 +151,8 @@ const char *translateObject(object_id_t object) { return ACS_CONTROLLER_STRING; case 0x43000003: return CORE_CONTROLLER_STRING; + case 0x43000006: + return GLOBAL_JSON_CFG_STRING; case 0x43400001: return THERMAL_CONTROLLER_STRING; case 0x44120006: diff --git a/mission/devices/devicedefinitions/gomspaceDefines.h b/mission/devices/devicedefinitions/gomspaceDefines.h index 92c02d6b..ddd346d7 100644 --- a/mission/devices/devicedefinitions/gomspaceDefines.h +++ b/mission/devices/devicedefinitions/gomspaceDefines.h @@ -28,6 +28,6 @@ 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_ */ diff --git a/mission/utility/CMakeLists.txt b/mission/utility/CMakeLists.txt index 128356bf..e2459ed1 100644 --- a/mission/utility/CMakeLists.txt +++ b/mission/utility/CMakeLists.txt @@ -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) diff --git a/mission/utility/GlobalConfigFileDefinitions.h b/mission/utility/GlobalConfigFileDefinitions.h new file mode 100644 index 00000000..2e7d133a --- /dev/null +++ b/mission/utility/GlobalConfigFileDefinitions.h @@ -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_ */ diff --git a/mission/utility/GlobalConfigHandler.cpp b/mission/utility/GlobalConfigHandler.cpp new file mode 100644 index 00000000..bb4b3d7d --- /dev/null +++ b/mission/utility/GlobalConfigHandler.cpp @@ -0,0 +1,269 @@ +/* + * GlobalConfigHandler.cpp + * + * Created on: May 3, 2022 + * Author: Jona Petri (IRS) + */ + +#include "GlobalConfigHandler.h" + +#include +#include +#include + +#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 +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 +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(ParamIds paramID, + double& data); +template ReturnValue_t GlobalConfigHandler::getConfigFileValue(ParamIds paramID, + int32_t& data); + +template ReturnValue_t GlobalConfigHandler::setConfigFileValue(ParamIds paramID, + double data); +template ReturnValue_t GlobalConfigHandler::setConfigFileValue(ParamIds paramID, + int32_t data); diff --git a/mission/utility/GlobalConfigHandler.h b/mission/utility/GlobalConfigHandler.h new file mode 100644 index 00000000..80e141c6 --- /dev/null +++ b/mission/utility/GlobalConfigHandler.h @@ -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 +#include +#include +#include +#include +#include + +#include +#include + +#include "GlobalConfigFileDefinitions.h" +#include "OBSWConfig.h" +#include "fsfw/parameters/HasParametersIF.h" +#include "fsfw/parameters/ParameterHelper.h" +#include "mission/memory/NVMParameterBase.h" + +static std::map 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 + ReturnValue_t setConfigFileValue(ParamIds paramID, T data); + template + 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_ */ diff --git a/tmtc b/tmtc index 52d91fe8..9cc079d7 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 52d91fe857e464a6e2d852d0c862dbec623eeef8 +Subproject commit 9cc079d71c96301e9200b6076f392e0733d14a53 diff --git a/unittest/controller/CMakeLists.txt b/unittest/controller/CMakeLists.txt index bfa3d11f..7680eefa 100644 --- a/unittest/controller/CMakeLists.txt +++ b/unittest/controller/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(${UNITTEST_NAME} PRIVATE testThermalController.cpp testAcsController.cpp -) \ No newline at end of file + testConfigFileHandler.cpp +) diff --git a/unittest/controller/testConfigFileHandler.cpp b/unittest/controller/testConfigFileHandler.cpp new file mode 100644 index 00000000..b8147e29 --- /dev/null +++ b/unittest/controller/testConfigFileHandler.cpp @@ -0,0 +1,65 @@ + + +#include +#include + +#include +#include +#include +#include + +#include "../testEnvironment.h" + +TEST_CASE("Configfile Handler", "[ConfigHandler]") { + sif::debug << "Testcase config file handler" << std::endl; + // Init handler + GlobalConfigHandler confighandler = GlobalConfigHandler(objects::GLOBAL_JSON_CFG, "JSON.config"); + REQUIRE(confighandler.initialize() == returnvalue::OK); + + // Reset handler + REQUIRE(confighandler.ResetConfigFile() == returnvalue::OK); + + // Get and set double as well as int values + double doubleData = 0.0; + REQUIRE(confighandler.getConfigFileValue(PARAM0, doubleData) == returnvalue::OK); + REQUIRE(doubleData == 5.0); + + doubleData = 55.9; + double doubleDataRead = 0; + REQUIRE(confighandler.setConfigFileValue(PARAM0, doubleData) == returnvalue::OK); + + REQUIRE(confighandler.getConfigFileValue(PARAM0, doubleDataRead) == returnvalue::OK); + REQUIRE(doubleDataRead == doubleData); + + REQUIRE(confighandler.WriteConfigFile() == returnvalue::OK); + + int intData = 0; + + REQUIRE(confighandler.getConfigFileValue(PARAM1, intData) == returnvalue::OK); + REQUIRE(intData == 905); + + intData = 1337; + int intDataRead = 0; + REQUIRE(confighandler.setConfigFileValue(PARAM1, intData) == returnvalue::OK); + + REQUIRE(confighandler.getConfigFileValue(PARAM1, intDataRead) == returnvalue::OK); + REQUIRE(intDataRead == intData); + + REQUIRE(confighandler.WriteConfigFile() == returnvalue::OK); + + // Check file name + REQUIRE(confighandler.getConfigFileName() == "JSON.config"); + + // Reset and check if it worked + REQUIRE(confighandler.ResetConfigFile() == returnvalue::OK); + + doubleData = 0.0; + REQUIRE(confighandler.getConfigFileValue(PARAM0, doubleData) == returnvalue::OK); + REQUIRE(doubleData == 5.0); + + // Test invalid Parameter + REQUIRE(confighandler.getConfigFileValue(PARAM2, doubleData) != + returnvalue::OK); // NVMParameterBase::KEY_NOT_EXISTS is private, why? + REQUIRE(confighandler.setConfigFileValue(PARAM2, doubleData) != returnvalue::OK); + std::filesystem::remove("JSON.config"); +} diff --git a/unittest/controller/testThermalController.cpp b/unittest/controller/testThermalController.cpp index a65ec69b..908ef1bb 100644 --- a/unittest/controller/testThermalController.cpp +++ b/unittest/controller/testThermalController.cpp @@ -15,7 +15,7 @@ TEST_CASE("Thermal Controller", "[ThermalController]") { new TemperatureSensorsDummy(); new SusDummy(); - testEnvironment::initialize(); + //testEnvironment::initialize(); ThermalController controller(THERMAL_CONTROLLER_ID, objects::NO_OBJECT); ReturnValue_t result = controller.initialize(); diff --git a/unittest/main.cpp b/unittest/main.cpp index 6438577c..760ff156 100644 --- a/unittest/main.cpp +++ b/unittest/main.cpp @@ -4,7 +4,7 @@ int main(int argc, char* argv[]) { testEnvironment::setup(); - + testEnvironment::initialize(); // Catch internal function call int result = Catch::Session().run(argc, argv);