Merge branch 'develop' into meier/pdec-config-persistent
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
This commit is contained in:
commit
d7ebc4dbe2
7
.gitignore
vendored
7
.gitignore
vendored
@ -12,8 +12,13 @@
|
|||||||
#vscode
|
#vscode
|
||||||
/.vscode
|
/.vscode
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/.idea/*
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
__pycache__
|
__pycache__
|
||||||
.idea
|
|
||||||
|
# CLion
|
||||||
|
!/.idea/cmake.xml
|
||||||
|
|
||||||
generators/*.db
|
generators/*.db
|
||||||
|
10
.run/Q7S FM.run.xml
Normal file
10
.run/Q7S FM.run.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Q7S FM" type="com.jetbrains.cidr.remote.gdbserver.type" factoryName="com.jetbrains.cidr.remote.gdbserver.factory" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="eive-obsw" TARGET_NAME="eive-obsw" CONFIG_NAME="Debug" version="1" RUN_TARGET_PROJECT_NAME="eive-obsw" RUN_TARGET_NAME="eive-obsw">
|
||||||
|
<custom-gdb-server version="1" gdb-connect="localhost:1234" executable="" warmup-ms="0" download-type="NONE" sshConfigName="Q7S FM" uploadFile="/tmp/eive-obsw" defaultGdbServerArgs=":1234 /tmp/eive-obsw">
|
||||||
|
<debugger kind="GDB" isBundled="true" />
|
||||||
|
</custom-gdb-server>
|
||||||
|
<method v="2">
|
||||||
|
<option name="CLION.COMPOUND.BUILD" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
42
CHANGELOG.md
42
CHANGELOG.md
@ -18,7 +18,49 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
- Linux GPS handler now checks the individual `*_SET` flags when analysing the `gpsd` struct.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/400
|
||||||
|
|
||||||
|
# [v1.32.0]
|
||||||
|
|
||||||
|
eive-tmtc: v2.16.1
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
- ADIS1650X: Added missing MDL_RANG pool entry for configuration set
|
- ADIS1650X: Added missing MDL_RANG pool entry for configuration set
|
||||||
|
- Bumped FSFW for bugfix in health service: No execution complete for targeted health announce
|
||||||
|
command.
|
||||||
|
- Removed matrix determinant calculation as part of the `MEKF`, which would take about
|
||||||
|
300ms of runtime
|
||||||
|
- Resetting the `MEKF` now also actually resets its stored state
|
||||||
|
- Bumped FSFW for bugfix in destination handler: Better error handling and able to process
|
||||||
|
destination folder path.
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Added basic persistent TM store for PUS telemetry and basic interface to dump and delete
|
||||||
|
telemetry. Implementation is based on a timed rotating files, with the addition that files
|
||||||
|
might be generated more often if the maximum file size of 8192 bytes is exceeded.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/320/files
|
||||||
|
- Commented out commanding of actuators as part of the `AcsController`
|
||||||
|
- Collection sets of the `AcsController` now get updated before running the actual ACS
|
||||||
|
algorithm
|
||||||
|
- `GpsController` now always gets scheduled
|
||||||
|
- The `CoreController` now initializes the initial clock from the time file as early as possible
|
||||||
|
(in the constructor) if possible, which should usually be the case.
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- Added basic persistent TM store for PUS telemetry and basic interface to dump and delete
|
||||||
|
telemetry.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/320/files
|
||||||
|
- `ExecutableComIfDummy` class to have a dummy for classes like the RTD polling class.
|
||||||
|
- Added `AcsController` action command to confirm solar array deployment, which then deletes
|
||||||
|
two files
|
||||||
|
- Added `AcsController` action command to reset `MEKF`
|
||||||
|
- `GpsCtrlDummy` now initializes the `gpsSet`
|
||||||
|
- `RwDummy` now initializes with a non faulty state
|
||||||
|
|
||||||
|
|
||||||
# [v1.31.1]
|
# [v1.31.1]
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
set(OBSW_VERSION_MAJOR 1)
|
set(OBSW_VERSION_MAJOR 1)
|
||||||
set(OBSW_VERSION_MINOR 31)
|
set(OBSW_VERSION_MINOR 32)
|
||||||
set(OBSW_VERSION_REVISION 1)
|
set(OBSW_VERSION_REVISION 0)
|
||||||
|
|
||||||
# set(CMAKE_VERBOSE TRUE)
|
# set(CMAKE_VERBOSE TRUE)
|
||||||
|
|
||||||
@ -223,6 +223,7 @@ set(LIB_JSON_PATH ${THIRD_PARTY_FOLDER}/json)
|
|||||||
|
|
||||||
set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
|
set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
|
||||||
set(EIVE_ADD_LINUX_FILES OFF)
|
set(EIVE_ADD_LINUX_FILES OFF)
|
||||||
|
set(FSFW_ADD_TMSTORAGE ON)
|
||||||
|
|
||||||
# Analyse different OS and architecture/target options, determine BSP_PATH,
|
# Analyse different OS and architecture/target options, determine BSP_PATH,
|
||||||
# display information about compiler etc.
|
# display information about compiler etc.
|
||||||
|
17
README.md
17
README.md
@ -18,6 +18,7 @@
|
|||||||
11. [Q7S OBC](#q7s)
|
11. [Q7S OBC](#q7s)
|
||||||
12. [Static Code Analysis](#static-code-analysis)
|
12. [Static Code Analysis](#static-code-analysis)
|
||||||
13. [Eclipse](#eclipse)
|
13. [Eclipse](#eclipse)
|
||||||
|
14. [CLion](#clion)
|
||||||
14. [Running the OBSW on a Raspberry Pi](#rpi)
|
14. [Running the OBSW on a Raspberry Pi](#rpi)
|
||||||
15. [Running OBSW on EGSE](#egse)
|
15. [Running OBSW on EGSE](#egse)
|
||||||
16. [Manually preparing sysroots to compile gpsd](#gpsd)
|
16. [Manually preparing sysroots to compile gpsd](#gpsd)
|
||||||
@ -1229,6 +1230,22 @@ Finally, you can convert the generated `.xml` file to HTML with the following co
|
|||||||
cppcheck-htmlreport --file=report.xml --report-dir=cppcheck --source-dir=..
|
cppcheck-htmlreport --file=report.xml --report-dir=cppcheck --source-dir=..
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# <a id="CLion"></a> CLion
|
||||||
|
|
||||||
|
CLion is the recommended IDE for the development of the hosted version of EIVE.
|
||||||
|
You can also set up CLion for cross-compilation of the primary OBSW.
|
||||||
|
|
||||||
|
There is a shared `.idea/cmake.xml` file to get started with this.
|
||||||
|
To make cross-compilation work, two special environment variables
|
||||||
|
need to be set:
|
||||||
|
|
||||||
|
- `ZYNQ_7020_ROOTFS` pointing to the root filesystem
|
||||||
|
- `CROSS_COMPILE` pointing to the the full path of the cross-compiler
|
||||||
|
without the specific tool suffix. For example, if the the cross-compiler
|
||||||
|
tools are located at `/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin`,
|
||||||
|
this variable would be set
|
||||||
|
to `/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf`
|
||||||
|
|
||||||
# <a id="eclipse"></a> Eclipse
|
# <a id="eclipse"></a> Eclipse
|
||||||
|
|
||||||
When using Eclipse, there are two special build variables in the project properties
|
When using Eclipse, there are two special build variables in the project properties
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <mission/tmtc/TmFunnelHandler.h>
|
#include <mission/tmtc/TmFunnelHandler.h>
|
||||||
#include <objects/systemObjectList.h>
|
#include <objects/systemObjectList.h>
|
||||||
|
|
||||||
|
#include "../mission/utility/DummySdCardManager.h"
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
#include "fsfw_tests/integration/task/TestTask.h"
|
#include "fsfw_tests/integration/task/TestTask.h"
|
||||||
@ -57,7 +58,8 @@ void ObjectFactory::produce(void* args) {
|
|||||||
Factory::setStaticFrameworkObjectIds();
|
Factory::setStaticFrameworkObjectIds();
|
||||||
PusTmFunnel* pusFunnel;
|
PusTmFunnel* pusFunnel;
|
||||||
CfdpTmFunnel* cfdpFunnel;
|
CfdpTmFunnel* cfdpFunnel;
|
||||||
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel);
|
auto sdcMan = new DummySdCardManager("/tmp");
|
||||||
|
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan);
|
||||||
|
|
||||||
auto* dummyGpioIF = new DummyGpioIF();
|
auto* dummyGpioIF = new DummyGpioIF();
|
||||||
auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0);
|
auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 260 translations.
|
* @brief Auto-generated event translation file. Contains 263 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-02-23 15:39:20
|
* Generated on: 2023-02-24 16:57:00
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -90,6 +90,8 @@ const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
|
|||||||
const char *STORE_ERROR_STRING = "STORE_ERROR";
|
const char *STORE_ERROR_STRING = "STORE_ERROR";
|
||||||
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
|
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
|
||||||
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
|
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
|
||||||
|
const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
|
||||||
|
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
|
||||||
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
||||||
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||||
@ -253,6 +255,7 @@ const char *REBOOT_HW_STRING = "REBOOT_HW";
|
|||||||
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
|
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
|
||||||
const char *VERSION_INFO_STRING = "VERSION_INFO";
|
const char *VERSION_INFO_STRING = "VERSION_INFO";
|
||||||
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
|
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
|
||||||
|
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||||
@ -433,6 +436,10 @@ const char *translateEvents(Event event) {
|
|||||||
return MSG_QUEUE_ERROR_STRING;
|
return MSG_QUEUE_ERROR_STRING;
|
||||||
case (10802):
|
case (10802):
|
||||||
return SERIALIZATION_ERROR_STRING;
|
return SERIALIZATION_ERROR_STRING;
|
||||||
|
case (10803):
|
||||||
|
return FILESTORE_ERROR_STRING;
|
||||||
|
case (10804):
|
||||||
|
return FILENAME_TOO_LARGE_ERROR_STRING;
|
||||||
case (11200):
|
case (11200):
|
||||||
return SAFE_RATE_VIOLATION_STRING;
|
return SAFE_RATE_VIOLATION_STRING;
|
||||||
case (11201):
|
case (11201):
|
||||||
@ -760,18 +767,20 @@ const char *translateEvents(Event event) {
|
|||||||
case (14006):
|
case (14006):
|
||||||
return CURRENT_IMAGE_INFO_STRING;
|
return CURRENT_IMAGE_INFO_STRING;
|
||||||
case (14100):
|
case (14100):
|
||||||
|
return POSSIBLE_FILE_CORRUPTION_STRING;
|
||||||
|
case (14200):
|
||||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||||
case (14101):
|
case (14201):
|
||||||
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
||||||
case (14102):
|
case (14202):
|
||||||
return SYRLINKS_OVERHEATING_STRING;
|
return SYRLINKS_OVERHEATING_STRING;
|
||||||
case (14103):
|
case (14203):
|
||||||
return PLOC_OVERHEATING_STRING;
|
return PLOC_OVERHEATING_STRING;
|
||||||
case (14104):
|
case (14204):
|
||||||
return OBC_OVERHEATING_STRING;
|
return OBC_OVERHEATING_STRING;
|
||||||
case (14105):
|
case (14205):
|
||||||
return HPA_OVERHEATING_STRING;
|
return HPA_OVERHEATING_STRING;
|
||||||
case (14106):
|
case (14206):
|
||||||
return PLPCDU_OVERHEATING_STRING;
|
return PLPCDU_OVERHEATING_STRING;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN_EVENT";
|
return "UNKNOWN_EVENT";
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 148 translations.
|
* Contains 154 translations.
|
||||||
* Generated on: 2023-02-23 15:39:20
|
* Generated on: 2023-02-24 16:57:00
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
@ -112,6 +112,7 @@ const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTIN
|
|||||||
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
|
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
|
||||||
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
|
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
|
||||||
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
|
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
|
||||||
|
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
|
||||||
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
|
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
|
||||||
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
|
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
|
||||||
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
|
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
|
||||||
@ -150,6 +151,11 @@ const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
|
|||||||
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
|
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
|
||||||
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
|
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
|
||||||
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
|
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
|
||||||
|
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
|
||||||
|
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
|
||||||
|
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
|
||||||
|
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
|
||||||
|
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
|
||||||
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
|
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
|
||||||
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
|
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
|
||||||
const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE";
|
const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE";
|
||||||
@ -369,6 +375,8 @@ const char *translateObject(object_id_t object) {
|
|||||||
return PUS_SERVICE_9_TIME_MGMT_STRING;
|
return PUS_SERVICE_9_TIME_MGMT_STRING;
|
||||||
case 0x53000011:
|
case 0x53000011:
|
||||||
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
|
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
|
||||||
|
case 0x53000015:
|
||||||
|
return PUS_SERVICE_15_TM_STORAGE_STRING;
|
||||||
case 0x53000017:
|
case 0x53000017:
|
||||||
return PUS_SERVICE_17_TEST_STRING;
|
return PUS_SERVICE_17_TEST_STRING;
|
||||||
case 0x53000020:
|
case 0x53000020:
|
||||||
@ -445,6 +453,16 @@ const char *translateObject(object_id_t object) {
|
|||||||
return TCS_SUBSYSTEM_STRING;
|
return TCS_SUBSYSTEM_STRING;
|
||||||
case 0x73010004:
|
case 0x73010004:
|
||||||
return COM_SUBSYSTEM_STRING;
|
return COM_SUBSYSTEM_STRING;
|
||||||
|
case 0x73020001:
|
||||||
|
return MISC_TM_STORE_STRING;
|
||||||
|
case 0x73020002:
|
||||||
|
return OK_TM_STORE_STRING;
|
||||||
|
case 0x73020003:
|
||||||
|
return NOT_OK_TM_STORE_STRING;
|
||||||
|
case 0x73020004:
|
||||||
|
return HK_TM_STORE_STRING;
|
||||||
|
case 0x73030000:
|
||||||
|
return CFDP_TM_STORE_STRING;
|
||||||
case 0x73500000:
|
case 0x73500000:
|
||||||
return CCSDS_IP_CORE_BRIDGE_STRING;
|
return CCSDS_IP_CORE_BRIDGE_STRING;
|
||||||
case 0x90000003:
|
case 0x90000003:
|
||||||
|
@ -95,46 +95,43 @@ void scheduling::initTasks() {
|
|||||||
sif::error << "Add component UDP Polling failed" << std::endl;
|
sif::error << "Add component UDP Polling failed" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PUS Services */
|
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
|
||||||
PeriodicTaskIF* pusVerification = factory->createPeriodicTask(
|
"PUS_HIGH_PRIO", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
||||||
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
result = pusHighPrio->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
|
||||||
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::error << "Object add component failed" << std::endl;
|
sif::error << "Object add component failed" << std::endl;
|
||||||
}
|
}
|
||||||
|
result = pusHighPrio->addComponent(objects::EVENT_MANAGER);
|
||||||
PeriodicTaskIF* eventHandling = factory->createPeriodicTask(
|
|
||||||
"EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
|
||||||
result = eventHandling->addComponent(objects::EVENT_MANAGER);
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("EVENT_MNGR", objects::EVENT_MANAGER);
|
scheduling::printAddObjectError("EVENT_MGMT", objects::EVENT_MANAGER);
|
||||||
}
|
}
|
||||||
result = eventHandling->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
|
result = pusHighPrio->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("PUS5", objects::PUS_SERVICE_5_EVENT_REPORTING);
|
scheduling::printAddObjectError("PUS5", objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
|
|
||||||
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
|
||||||
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
scheduling::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
|
||||||
}
|
|
||||||
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
|
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
|
scheduling::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
|
||||||
|
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
|
||||||
|
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
scheduling::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||||
|
}
|
||||||
result = pusHighPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
|
result = pusHighPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
|
scheduling::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
|
|
||||||
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
|
|
||||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
scheduling::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||||
}
|
}
|
||||||
|
result = pusMedPrio->addComponent(objects::PUS_SERVICE_15_TM_STORAGE);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
scheduling::printAddObjectError("PUS15", objects::PUS_SERVICE_15_TM_STORAGE);
|
||||||
|
}
|
||||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
|
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
|
scheduling::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
|
||||||
@ -143,10 +140,7 @@ void scheduling::initTasks() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
|
scheduling::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
|
||||||
}
|
}
|
||||||
|
result = pusMedPrio->addComponent(objects::PUS_SERVICE_17_TEST);
|
||||||
PeriodicTaskIF* pusLowPrio = factory->createPeriodicTask(
|
|
||||||
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
|
|
||||||
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
|
scheduling::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
|
||||||
}
|
}
|
||||||
@ -220,11 +214,8 @@ void scheduling::initTasks() {
|
|||||||
udpPollingTask->startTask();
|
udpPollingTask->startTask();
|
||||||
tcpPollingTask->startTask();
|
tcpPollingTask->startTask();
|
||||||
|
|
||||||
pusVerification->startTask();
|
|
||||||
eventHandling->startTask();
|
|
||||||
pusHighPrio->startTask();
|
pusHighPrio->startTask();
|
||||||
pusMedPrio->startTask();
|
pusMedPrio->startTask();
|
||||||
pusLowPrio->startTask();
|
|
||||||
|
|
||||||
pstTask->startTask();
|
pstTask->startTask();
|
||||||
thermalTask->startTask();
|
thermalTask->startTask();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
target_sources(${OBSW_NAME} PUBLIC InitMission.cpp main.cpp gpioInit.cpp
|
target_sources(${OBSW_NAME} PUBLIC InitMission.cpp main.cpp gpioInit.cpp
|
||||||
ObjectFactory.cpp RPiSdCardManager.cpp)
|
ObjectFactory.cpp)
|
||||||
|
|
||||||
add_subdirectory(boardconfig)
|
add_subdirectory(boardconfig)
|
||||||
add_subdirectory(boardtest)
|
add_subdirectory(boardtest)
|
||||||
|
@ -82,7 +82,7 @@ void ObjectFactory::produce(void* args) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OBSW_ADD_SCEX_DEVICE == 1
|
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||||
auto* sdcMan = new RPiSdCardManager("/tmp");
|
auto* sdcMan = new DummySdCardManager("/tmp");
|
||||||
createScexComponents(uart::DEV, pwrSwitcher, *sdcMan, true, std::nullopt);
|
createScexComponents(uart::DEV, pwrSwitcher, *sdcMan, true, std::nullopt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#include "RPiSdCardManager.h"
|
|
||||||
|
|
||||||
RPiSdCardManager::RPiSdCardManager(std::string prefix) : prefix(std::move(prefix)) {}
|
|
||||||
|
|
||||||
const std::string& RPiSdCardManager::getCurrentMountPrefix() const { return prefix; }
|
|
||||||
|
|
||||||
bool RPiSdCardManager::isSdCardUsable(sd::SdCard sdCard) { return true; }
|
|
||||||
|
|
||||||
std::optional<sd::SdCard> RPiSdCardManager::getPreferredSdCard() const { return std::nullopt; }
|
|
||||||
|
|
||||||
void RPiSdCardManager::setActiveSdCard(sd::SdCard sdCard) {}
|
|
||||||
|
|
||||||
std::optional<sd::SdCard> RPiSdCardManager::getActiveSdCard() const { return std::nullopt; }
|
|
@ -49,6 +49,8 @@ CoreController::CoreController(object_id_t objectId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurrentBootCopy(CURRENT_CHIP, CURRENT_COPY);
|
getCurrentBootCopy(CURRENT_CHIP, CURRENT_COPY);
|
||||||
|
|
||||||
|
initClockFromTimeFile();
|
||||||
} catch (const std::filesystem::filesystem_error &e) {
|
} catch (const std::filesystem::filesystem_error &e) {
|
||||||
sif::error << "CoreController::CoreController: Failed with exception " << e.what() << std::endl;
|
sif::error << "CoreController::CoreController: Failed with exception " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
@ -159,6 +161,9 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
|
|||||||
}
|
}
|
||||||
sdcMan->setActiveSdCard(sdInfo.active);
|
sdcMan->setActiveSdCard(sdInfo.active);
|
||||||
currMntPrefix = sdcMan->getCurrentMountPrefix();
|
currMntPrefix = sdcMan->getCurrentMountPrefix();
|
||||||
|
if (currMntPrefix == "") {
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
if (BLOCKING_SD_INIT) {
|
if (BLOCKING_SD_INIT) {
|
||||||
result = initSdCardBlocking();
|
result = initSdCardBlocking();
|
||||||
if (result != returnvalue::OK and result != SdCardManager::ALREADY_MOUNTED) {
|
if (result != returnvalue::OK and result != SdCardManager::ALREADY_MOUNTED) {
|
||||||
@ -1266,10 +1271,12 @@ void CoreController::performMountedSdCardOperations() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "CoreController::CoreController: Boot copy init" << std::endl;
|
sif::warning << "CoreController::CoreController: Boot copy init" << std::endl;
|
||||||
}
|
}
|
||||||
|
if (not timeFileInitDone) {
|
||||||
initClockFromTimeFile();
|
initClockFromTimeFile();
|
||||||
|
}
|
||||||
performRebootFileHandling(false);
|
performRebootFileHandling(false);
|
||||||
}
|
}
|
||||||
timeFileHandler();
|
backupTimeFileHandler();
|
||||||
};
|
};
|
||||||
bool someSdCardActive = false;
|
bool someSdCardActive = false;
|
||||||
if (sdInfo.active == sd::SdCard::SLOT_0 and sdcMan->isSdCardUsable(sd::SdCard::SLOT_0)) {
|
if (sdInfo.active == sd::SdCard::SLOT_0 and sdcMan->isSdCardUsable(sd::SdCard::SLOT_0)) {
|
||||||
@ -1783,7 +1790,7 @@ void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::C
|
|||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootFile(rebootFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CoreController::timeFileHandler() {
|
ReturnValue_t CoreController::backupTimeFileHandler() {
|
||||||
// Always set time. We could only set it if it is updated by GPS, but then the backup time would
|
// Always set time. We could only set it if it is updated by GPS, but then the backup time would
|
||||||
// become obsolete on GPS problems.
|
// become obsolete on GPS problems.
|
||||||
if (opDivider10.check()) {
|
if (opDivider10.check()) {
|
||||||
@ -1793,14 +1800,14 @@ ReturnValue_t CoreController::timeFileHandler() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
std::string fileName = currMntPrefix + TIME_FILE;
|
std::string fileName = currMntPrefix + BACKUP_TIME_FILE;
|
||||||
std::ofstream timeFile(fileName);
|
std::ofstream timeFile(fileName);
|
||||||
if (not timeFile.good()) {
|
if (not timeFile.good()) {
|
||||||
sif::error << "CoreController::timeFileHandler: Error opening time file: " << strerror(errno)
|
sif::error << "CoreController::timeFileHandler: Error opening time file: " << strerror(errno)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
timeFile << "UNIX SECONDS: " << currentTime.tv_sec << std::endl;
|
timeFile << "UNIX SECONDS: " << currentTime.tv_sec + BOOT_OFFSET_SECONDS << std::endl;
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
@ -1808,8 +1815,8 @@ ReturnValue_t CoreController::timeFileHandler() {
|
|||||||
ReturnValue_t CoreController::initClockFromTimeFile() {
|
ReturnValue_t CoreController::initClockFromTimeFile() {
|
||||||
using namespace GpsHyperion;
|
using namespace GpsHyperion;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
std::string fileName = currMntPrefix + TIME_FILE;
|
std::string fileName = currMntPrefix + BACKUP_TIME_FILE;
|
||||||
if (std::filesystem::exists(fileName) and
|
if (sdcMan->isSdCardUsable(std::nullopt) and std::filesystem::exists(fileName) and
|
||||||
((gpsFix == FixMode::UNKNOWN or gpsFix == FixMode::NOT_SEEN) or
|
((gpsFix == FixMode::UNKNOWN or gpsFix == FixMode::NOT_SEEN) or
|
||||||
not utility::timeSanityCheck())) {
|
not utility::timeSanityCheck())) {
|
||||||
ifstream timeFile(fileName);
|
ifstream timeFile(fileName);
|
||||||
@ -1837,6 +1844,7 @@ ReturnValue_t CoreController::initClockFromTimeFile() {
|
|||||||
sif::info << "Setting system time from time files: " << std::put_time(time, "%c %Z")
|
sif::info << "Setting system time from time files: " << std::put_time(time, "%c %Z")
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
timeFileInitDone = true;
|
||||||
return Clock::setClock(¤tTime);
|
return Clock::setClock(¤tTime);
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
|
@ -58,13 +58,14 @@ class CoreController : public ExtendedControllerBase {
|
|||||||
|
|
||||||
static constexpr char VERSION_FILE_NAME[] = "version.txt";
|
static constexpr char VERSION_FILE_NAME[] = "version.txt";
|
||||||
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
|
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
|
||||||
static constexpr char TIME_FILE_NAME[] = "time.txt";
|
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
|
||||||
|
|
||||||
const std::string VERSION_FILE =
|
const std::string VERSION_FILE =
|
||||||
"/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME);
|
"/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME);
|
||||||
const std::string REBOOT_FILE =
|
const std::string REBOOT_FILE =
|
||||||
"/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME);
|
"/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME);
|
||||||
const std::string TIME_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(TIME_FILE_NAME);
|
const std::string BACKUP_TIME_FILE =
|
||||||
|
"/" + std::string(CONF_FOLDER) + "/" + std::string(TIME_FILE_NAME);
|
||||||
|
|
||||||
static constexpr char CHIP_0_COPY_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-nom-rootfs";
|
static constexpr char CHIP_0_COPY_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-nom-rootfs";
|
||||||
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
|
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
|
||||||
@ -160,6 +161,7 @@ class CoreController : public ExtendedControllerBase {
|
|||||||
bool sdInitFinished() const;
|
bool sdInitFinished() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr uint32_t BOOT_OFFSET_SECONDS = 15;
|
||||||
static constexpr MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
|
static constexpr MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
|
||||||
static constexpr uint32_t MUTEX_TIMEOUT = 20;
|
static constexpr uint32_t MUTEX_TIMEOUT = 20;
|
||||||
// Designated value for rechecking FIFO open
|
// Designated value for rechecking FIFO open
|
||||||
@ -221,6 +223,7 @@ class CoreController : public ExtendedControllerBase {
|
|||||||
|
|
||||||
RebootFile rebootFile = {};
|
RebootFile rebootFile = {};
|
||||||
std::string currMntPrefix;
|
std::string currMntPrefix;
|
||||||
|
bool timeFileInitDone = false;
|
||||||
bool performOneShotSdCardOpsSwitch = false;
|
bool performOneShotSdCardOpsSwitch = false;
|
||||||
uint8_t shortSdCardCdCounter = 0;
|
uint8_t shortSdCardCdCounter = 0;
|
||||||
#if OBSW_THREAD_TRACING == 1
|
#if OBSW_THREAD_TRACING == 1
|
||||||
@ -258,7 +261,7 @@ class CoreController : public ExtendedControllerBase {
|
|||||||
|
|
||||||
ReturnValue_t initClockFromTimeFile();
|
ReturnValue_t initClockFromTimeFile();
|
||||||
ReturnValue_t performSdCardCheck();
|
ReturnValue_t performSdCardCheck();
|
||||||
ReturnValue_t timeFileHandler();
|
ReturnValue_t backupTimeFileHandler();
|
||||||
ReturnValue_t initBootCopyFile();
|
ReturnValue_t initBootCopyFile();
|
||||||
ReturnValue_t initWatchdogFifo();
|
ReturnValue_t initWatchdogFifo();
|
||||||
ReturnValue_t initSdCardBlocking();
|
ReturnValue_t initSdCardBlocking();
|
||||||
|
@ -187,14 +187,12 @@ void scheduling::initTasks() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OBSW_ADD_GPS_CTRL == 1
|
|
||||||
PeriodicTaskIF* gpsTask = factory->createPeriodicTask(
|
PeriodicTaskIF* gpsTask = factory->createPeriodicTask(
|
||||||
"GPS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc);
|
"GPS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc);
|
||||||
result = gpsTask->addComponent(objects::GPS_CONTROLLER);
|
result = gpsTask->addComponent(objects::GPS_CONTROLLER);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("GPS_CTRL", objects::GPS_CONTROLLER);
|
scheduling::printAddObjectError("GPS_CTRL", objects::GPS_CONTROLLER);
|
||||||
}
|
}
|
||||||
#endif /* OBSW_ADD_GPS_CTRL */
|
|
||||||
|
|
||||||
#if OBSW_ADD_RW == 1
|
#if OBSW_ADD_RW == 1
|
||||||
PeriodicTaskIF* rwPolling = factory->createPeriodicTask(
|
PeriodicTaskIF* rwPolling = factory->createPeriodicTask(
|
||||||
@ -378,9 +376,7 @@ void scheduling::initTasks() {
|
|||||||
#if OBSW_ADD_RW == 1
|
#if OBSW_ADD_RW == 1
|
||||||
rwPolling->startTask();
|
rwPolling->startTask();
|
||||||
#endif
|
#endif
|
||||||
#if OBSW_ADD_GPS_CTRL == 1
|
|
||||||
gpsTask->startTask();
|
gpsTask->startTask();
|
||||||
#endif
|
|
||||||
acsSysTask->startTask();
|
acsSysTask->startTask();
|
||||||
if (not tcsSystemTask->isEmpty()) {
|
if (not tcsSystemTask->isEmpty()) {
|
||||||
tcsSystemTask->startTask();
|
tcsSystemTask->startTask();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <fsfw/power/DummyPowerSwitcher.h>
|
#include <fsfw/power/DummyPowerSwitcher.h>
|
||||||
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
|
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
|
||||||
#include <mission/system/tree/system.h>
|
#include <mission/system/tree/system.h>
|
||||||
|
#include <mission/utility/DummySdCardManager.h>
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "bsp_q7s/core/CoreController.h"
|
#include "bsp_q7s/core/CoreController.h"
|
||||||
@ -22,7 +23,8 @@ void ObjectFactory::produce(void* args) {
|
|||||||
HealthTableIF* healthTable = nullptr;
|
HealthTableIF* healthTable = nullptr;
|
||||||
PusTmFunnel* pusFunnel = nullptr;
|
PusTmFunnel* pusFunnel = nullptr;
|
||||||
CfdpTmFunnel* cfdpFunnel = nullptr;
|
CfdpTmFunnel* cfdpFunnel = nullptr;
|
||||||
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel);
|
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
||||||
|
*SdCardManager::instance());
|
||||||
|
|
||||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
SerialComIF* uartComIF = nullptr;
|
SerialComIF* uartComIF = nullptr;
|
||||||
|
@ -18,7 +18,8 @@ void ObjectFactory::produce(void* args) {
|
|||||||
HealthTableIF* healthTable = nullptr;
|
HealthTableIF* healthTable = nullptr;
|
||||||
PusTmFunnel* pusFunnel = nullptr;
|
PusTmFunnel* pusFunnel = nullptr;
|
||||||
CfdpTmFunnel* cfdpFunnel = nullptr;
|
CfdpTmFunnel* cfdpFunnel = nullptr;
|
||||||
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel);
|
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
||||||
|
*SdCardManager::instance());
|
||||||
|
|
||||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
SerialComIF* uartComIF = nullptr;
|
SerialComIF* uartComIF = nullptr;
|
||||||
|
@ -410,9 +410,12 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& SdCardManager::getCurrentMountPrefix() const {
|
const char* SdCardManager::getCurrentMountPrefix() const {
|
||||||
MutexGuard mg(mutex);
|
MutexGuard mg(mutex);
|
||||||
return currentPrefix;
|
if (currentPrefix.has_value()) {
|
||||||
|
return currentPrefix.value().c_str();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) {
|
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) {
|
||||||
|
@ -187,7 +187,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
|
|||||||
* @param prefSdCardPtr
|
* @param prefSdCardPtr
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
const std::string& getCurrentMountPrefix() const override;
|
const char* getCurrentMountPrefix() const override;
|
||||||
|
|
||||||
OpStatus checkCurrentOp(Operations& currentOp);
|
OpStatus checkCurrentOp(Operations& currentOp);
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
|
|||||||
void processSdStatusLine(SdStatePair& active, std::string& line, uint8_t& idx,
|
void processSdStatusLine(SdStatePair& active, std::string& line, uint8_t& idx,
|
||||||
sd::SdCard& currentSd);
|
sd::SdCard& currentSd);
|
||||||
|
|
||||||
std::string currentPrefix;
|
std::optional<std::string> currentPrefix;
|
||||||
|
|
||||||
static SdCardManager* INSTANCE;
|
static SdCardManager* INSTANCE;
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
std::filesystem::path fshelpers::getPrefixedPath(SdCardManager &man,
|
std::filesystem::path fshelpers::getPrefixedPath(SdCardManager &man,
|
||||||
std::filesystem::path pathWihtoutPrefix) {
|
std::filesystem::path pathWihtoutPrefix) {
|
||||||
auto prefix = man.getCurrentMountPrefix();
|
auto prefix = man.getCurrentMountPrefix();
|
||||||
|
if (prefix == nullptr) {
|
||||||
|
return pathWihtoutPrefix;
|
||||||
|
}
|
||||||
auto resPath = prefix / pathWihtoutPrefix;
|
auto resPath = prefix / pathWihtoutPrefix;
|
||||||
return resPath;
|
return resPath;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@ static constexpr uint32_t SCHED_BLOCK_1_SUS_READ_MS = 15;
|
|||||||
static constexpr uint32_t SCHED_BLOCK_2_SENSOR_READ_MS = 30;
|
static constexpr uint32_t SCHED_BLOCK_2_SENSOR_READ_MS = 30;
|
||||||
static constexpr uint32_t SCHED_BLOCK_3_READ_IMTQ_MGM_MS = 42;
|
static constexpr uint32_t SCHED_BLOCK_3_READ_IMTQ_MGM_MS = 42;
|
||||||
static constexpr uint32_t SCHED_BLOCK_4_ACS_CTRL_MS = 45;
|
static constexpr uint32_t SCHED_BLOCK_4_ACS_CTRL_MS = 45;
|
||||||
static constexpr uint32_t SCHED_BLOCK_5_ACTUATOR_MS = 50;
|
static constexpr uint32_t SCHED_BLOCK_5_ACTUATOR_MS = 55;
|
||||||
static constexpr uint32_t SCHED_BLOCK_6_IMTQ_BLOCK_2_MS = 90;
|
static constexpr uint32_t SCHED_BLOCK_6_IMTQ_BLOCK_2_MS = 95;
|
||||||
static constexpr uint32_t SCHED_BLOCK_RTD = 150;
|
static constexpr uint32_t SCHED_BLOCK_RTD = 150;
|
||||||
static constexpr uint32_t SCHED_BLOCK_7_RW_READ_MS = 300;
|
static constexpr uint32_t SCHED_BLOCK_7_RW_READ_MS = 300;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ enum : uint8_t {
|
|||||||
CORE = 140,
|
CORE = 140,
|
||||||
TCS_CONTROLLER = 141,
|
TCS_CONTROLLER = 141,
|
||||||
COM_SUBSYSTEM = 142,
|
COM_SUBSYSTEM = 142,
|
||||||
|
PERSISTENT_TM_STORE = 143,
|
||||||
COMMON_SUBSYSTEM_ID_END
|
COMMON_SUBSYSTEM_ID_END
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -152,6 +152,11 @@ enum commonObjects : uint32_t {
|
|||||||
CFDP_TM_FUNNEL = 0x73000102,
|
CFDP_TM_FUNNEL = 0x73000102,
|
||||||
CFDP_HANDLER = 0x73000205,
|
CFDP_HANDLER = 0x73000205,
|
||||||
CFDP_DISTRIBUTOR = 0x73000206,
|
CFDP_DISTRIBUTOR = 0x73000206,
|
||||||
|
MISC_TM_STORE = 0x73020001,
|
||||||
|
OK_TM_STORE = 0x73020002,
|
||||||
|
NOT_OK_TM_STORE = 0x73020003,
|
||||||
|
HK_TM_STORE = 0x73020004,
|
||||||
|
CFDP_TM_STORE = 0x73030000,
|
||||||
|
|
||||||
// Other stuff
|
// Other stuff
|
||||||
THERMAL_TEMP_INSERTER = 0x90000003,
|
THERMAL_TEMP_INSERTER = 0x90000003,
|
||||||
|
@ -35,14 +35,13 @@ enum commonClassIds : uint8_t {
|
|||||||
SA_DEPL_HANDLER, // SADPL
|
SA_DEPL_HANDLER, // SADPL
|
||||||
MPSOC_RETURN_VALUES_IF, // MPSOCRTVIF
|
MPSOC_RETURN_VALUES_IF, // MPSOCRTVIF
|
||||||
SUPV_RETURN_VALUES_IF, // SPVRTVIF
|
SUPV_RETURN_VALUES_IF, // SPVRTVIF
|
||||||
ACS_KALMAN, // ACSKAL
|
ACS_CTRL, // ACSCTRL
|
||||||
|
ACS_MEKF, // ACSMEKF
|
||||||
ACS_SAFE, // ACSSAF
|
ACS_SAFE, // ACSSAF
|
||||||
ACS_PTG, // ACSPTG
|
ACS_PTG, // ACSPTG
|
||||||
ACS_DETUMBLE, // ACSDTB
|
ACS_DETUMBLE, // ACSDTB
|
||||||
ACS_MEKF, // ACSMEK
|
|
||||||
COMMON_CLASS_ID_END // [EXPORT] : [END]
|
COMMON_CLASS_ID_END // [EXPORT] : [END]
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* COMMON_CONFIG_COMMONCLASSIDS_H_ */
|
#endif /* COMMON_CONFIG_COMMONCLASSIDS_H_ */
|
||||||
|
@ -12,6 +12,7 @@ enum Ids {
|
|||||||
PUS_SERVICE_8 = 8,
|
PUS_SERVICE_8 = 8,
|
||||||
PUS_SERVICE_9 = 9,
|
PUS_SERVICE_9 = 9,
|
||||||
PUS_SERVICE_11 = 11,
|
PUS_SERVICE_11 = 11,
|
||||||
|
PUS_SERVICE_15 = 15,
|
||||||
PUS_SERVICE_17 = 17,
|
PUS_SERVICE_17 = 17,
|
||||||
PUS_SERVICE_19 = 19,
|
PUS_SERVICE_19 = 19,
|
||||||
PUS_SERVICE_20 = 20,
|
PUS_SERVICE_20 = 20,
|
||||||
|
@ -20,6 +20,7 @@ target_sources(
|
|||||||
GyroL3GD20Dummy.cpp
|
GyroL3GD20Dummy.cpp
|
||||||
MgmLIS3MDLDummy.cpp
|
MgmLIS3MDLDummy.cpp
|
||||||
PlPcduDummy.cpp
|
PlPcduDummy.cpp
|
||||||
|
ExecutableComIfDummy.cpp
|
||||||
ScexDummy.cpp
|
ScexDummy.cpp
|
||||||
CoreControllerDummy.cpp
|
CoreControllerDummy.cpp
|
||||||
PlocMpsocDummy.cpp
|
PlocMpsocDummy.cpp
|
||||||
|
27
dummies/ExecutableComIfDummy.cpp
Normal file
27
dummies/ExecutableComIfDummy.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <dummies/ExecutableComIfDummy.h>
|
||||||
|
|
||||||
|
ExecutableComIfDummy::ExecutableComIfDummy(object_id_t objectId) : SystemObject(objectId) {}
|
||||||
|
|
||||||
|
ReturnValue_t ExecutableComIfDummy::initializeInterface(CookieIF *cookie) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ExecutableComIfDummy::sendMessage(CookieIF *cookie, const uint8_t *sendData,
|
||||||
|
size_t sendLen) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ExecutableComIfDummy::getSendSuccess(CookieIF *cookie) { return returnvalue::OK; }
|
||||||
|
|
||||||
|
ReturnValue_t ExecutableComIfDummy::requestReceiveMessage(CookieIF *cookie, size_t requestLen) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ExecutableComIfDummy::performOperation(uint8_t operationCode) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ExecutableComIfDummy::readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
|
||||||
|
size_t *size) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
21
dummies/ExecutableComIfDummy.h
Normal file
21
dummies/ExecutableComIfDummy.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef DUMMIES_EXECUTABLECOMIFDUMMY_H_
|
||||||
|
#define DUMMIES_EXECUTABLECOMIFDUMMY_H_
|
||||||
|
|
||||||
|
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||||
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
|
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||||
|
|
||||||
|
class ExecutableComIfDummy : public ExecutableObjectIF,
|
||||||
|
public DeviceCommunicationIF,
|
||||||
|
public SystemObject {
|
||||||
|
public:
|
||||||
|
ExecutableComIfDummy(object_id_t objectId);
|
||||||
|
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||||
|
ReturnValue_t initializeInterface(CookieIF *cookie) override;
|
||||||
|
ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) override;
|
||||||
|
ReturnValue_t getSendSuccess(CookieIF *cookie) override;
|
||||||
|
ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
|
||||||
|
ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* DUMMIES_EXECUTABLECOMIFDUMMY_H_ */
|
@ -1,6 +1,7 @@
|
|||||||
#include "GpsCtrlDummy.h"
|
#include "GpsCtrlDummy.h"
|
||||||
|
|
||||||
GpsCtrlDummy::GpsCtrlDummy(object_id_t objectId) : ExtendedControllerBase(objectId, 20) {}
|
GpsCtrlDummy::GpsCtrlDummy(object_id_t objectId)
|
||||||
|
: ExtendedControllerBase(objectId, 20), gpsSet(this) {}
|
||||||
|
|
||||||
ReturnValue_t GpsCtrlDummy::handleCommandMessage(CommandMessage* message) {
|
ReturnValue_t GpsCtrlDummy::handleCommandMessage(CommandMessage* message) {
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
@ -13,9 +14,23 @@ ReturnValue_t GpsCtrlDummy::checkModeCommand(Mode_t mode, Submode_t submode,
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalPoolDataSetBase* GpsCtrlDummy::getDataSetHandle(sid_t sid) { return &gpsSet; }
|
||||||
|
|
||||||
ReturnValue_t GpsCtrlDummy::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
ReturnValue_t GpsCtrlDummy::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
LocalDataPoolManager& poolManager) {
|
LocalDataPoolManager& poolManager) {
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::ALTITUDE, new PoolEntry<double>({537222.3469}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::LONGITUDE, new PoolEntry<double>({-8.8579}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::LATITUDE, new PoolEntry<double>({49.5952}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::SPEED, new PoolEntry<double>({0}));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::YEAR, new PoolEntry<uint16_t>({2023}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::MONTH, new PoolEntry<uint8_t>({5}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::DAY, new PoolEntry<uint8_t>({16}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::HOURS, new PoolEntry<uint8_t>({1}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::MINUTES, new PoolEntry<uint8_t>({0}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::SECONDS, new PoolEntry<uint8_t>({0}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>({1684191600}, true));
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
||||||
|
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPoolDataSetBase* GpsCtrlDummy::getDataSetHandle(sid_t sid) { return nullptr; }
|
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
#define DUMMIES_GPSCTRLDUMMY_H_
|
#define DUMMIES_GPSCTRLDUMMY_H_
|
||||||
|
|
||||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||||
|
#include <mission/devices/devicedefinitions/GPSDefinitions.h>
|
||||||
|
|
||||||
class GpsCtrlDummy : public ExtendedControllerBase {
|
class GpsCtrlDummy : public ExtendedControllerBase {
|
||||||
public:
|
public:
|
||||||
GpsCtrlDummy(object_id_t objectId);
|
GpsCtrlDummy(object_id_t objectId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GpsPrimaryDataset gpsSet;
|
||||||
|
|
||||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||||
void performControlOperation() override;
|
void performControlOperation() override;
|
||||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
|
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
|
||||||
|
|
||||||
PduDummy::PduDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
PduDummy::PduDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||||
: DeviceHandlerBase(objectId, comif, comCookie) {}
|
: DeviceHandlerBase(objectId, comif, comCookie),
|
||||||
|
coreHk(this, static_cast<uint32_t>(P60System::SetIds::CORE)) {}
|
||||||
|
|
||||||
PduDummy::~PduDummy() {}
|
PduDummy::~PduDummy() {}
|
||||||
|
|
||||||
@ -38,5 +39,7 @@ uint32_t PduDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return
|
|||||||
ReturnValue_t PduDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
ReturnValue_t PduDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||||
LocalDataPoolManager &poolManager) {
|
LocalDataPoolManager &poolManager) {
|
||||||
localDataPoolMap.emplace(PDU::pool::PDU_TEMPERATURE, new PoolEntry<float>({0}));
|
localDataPoolMap.emplace(PDU::pool::PDU_TEMPERATURE, new PoolEntry<float>({0}));
|
||||||
|
localDataPoolMap.emplace(PDU::pool::PDU_VOLTAGES, &pduVoltages);
|
||||||
|
localDataPoolMap.emplace(PDU::pool::PDU_CURRENTS, &pduCurrents);
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||||
|
|
||||||
|
#include "mission/devices/devicedefinitions/GomspaceDefinitions.h"
|
||||||
|
|
||||||
class PduDummy : public DeviceHandlerBase {
|
class PduDummy : public DeviceHandlerBase {
|
||||||
public:
|
public:
|
||||||
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
|
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
|
||||||
@ -15,6 +17,10 @@ class PduDummy : public DeviceHandlerBase {
|
|||||||
virtual ~PduDummy();
|
virtual ~PduDummy();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
PDU::PduCoreHk coreHk;
|
||||||
|
PoolEntry<int16_t> pduVoltages = PoolEntry<int16_t>(9);
|
||||||
|
PoolEntry<int16_t> pduCurrents = PoolEntry<int16_t>(9);
|
||||||
|
|
||||||
void doStartUp() override;
|
void doStartUp() override;
|
||||||
void doShutDown() override;
|
void doShutDown() override;
|
||||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||||
|
@ -41,7 +41,7 @@ ReturnValue_t RwDummy::initializeLocalDataPool(localpool::DataPool &localDataPoo
|
|||||||
|
|
||||||
localDataPoolMap.emplace(rws::CURR_SPEED, new PoolEntry<int32_t>({0}));
|
localDataPoolMap.emplace(rws::CURR_SPEED, new PoolEntry<int32_t>({0}));
|
||||||
localDataPoolMap.emplace(rws::REFERENCE_SPEED, new PoolEntry<int32_t>({0}));
|
localDataPoolMap.emplace(rws::REFERENCE_SPEED, new PoolEntry<int32_t>({0}));
|
||||||
localDataPoolMap.emplace(rws::STATE, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(rws::STATE, new PoolEntry<uint8_t>({1}, true));
|
||||||
localDataPoolMap.emplace(rws::CLC_MODE, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(rws::CLC_MODE, new PoolEntry<uint8_t>({0}));
|
||||||
|
|
||||||
localDataPoolMap.emplace(rws::LAST_RESET_STATUS, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(rws::LAST_RESET_STATUS, new PoolEntry<uint8_t>({0}));
|
||||||
|
@ -37,7 +37,7 @@ ReturnValue_t SusDummy::initializeLocalDataPool(localpool::DataPool &localDataPo
|
|||||||
LocalDataPoolManager &poolManager) {
|
LocalDataPoolManager &poolManager) {
|
||||||
localDataPoolMap.emplace(SUS::SusPoolIds::TEMPERATURE_C, new PoolEntry<float>({0}, 1, true));
|
localDataPoolMap.emplace(SUS::SusPoolIds::TEMPERATURE_C, new PoolEntry<float>({0}, 1, true));
|
||||||
localDataPoolMap.emplace(SUS::SusPoolIds::CHANNEL_VEC,
|
localDataPoolMap.emplace(SUS::SusPoolIds::CHANNEL_VEC,
|
||||||
new PoolEntry<uint16_t>({0, 0, 0, 0, 0, 0}, true));
|
new PoolEntry<uint16_t>({2603, 781, 2760, 2048, 4056, 0}, true));
|
||||||
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <dummies/ComCookieDummy.h>
|
#include <dummies/ComCookieDummy.h>
|
||||||
#include <dummies/ComIFDummy.h>
|
#include <dummies/ComIFDummy.h>
|
||||||
#include <dummies/CoreControllerDummy.h>
|
#include <dummies/CoreControllerDummy.h>
|
||||||
|
#include <dummies/ExecutableComIfDummy.h>
|
||||||
#include <dummies/GpsCtrlDummy.h>
|
#include <dummies/GpsCtrlDummy.h>
|
||||||
#include <dummies/GpsDhbDummy.h>
|
#include <dummies/GpsDhbDummy.h>
|
||||||
#include <dummies/GyroAdisDummy.h>
|
#include <dummies/GyroAdisDummy.h>
|
||||||
@ -45,7 +46,7 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
|||||||
new CoreControllerDummy(objects::CORE_CONTROLLER);
|
new CoreControllerDummy(objects::CORE_CONTROLLER);
|
||||||
}
|
}
|
||||||
if (cfg.addRtdComIFDummy) {
|
if (cfg.addRtdComIFDummy) {
|
||||||
new ComIFDummy(objects::SPI_RTD_COM_IF);
|
new ExecutableComIfDummy(objects::SPI_RTD_COM_IF);
|
||||||
}
|
}
|
||||||
std::array<object_id_t, 4> rwIds = {objects::RW1, objects::RW2, objects::RW3, objects::RW4};
|
std::array<object_id_t, 4> rwIds = {objects::RW1, objects::RW2, objects::RW3, objects::RW4};
|
||||||
std::array<DeviceHandlerBase*, 4> rws;
|
std::array<DeviceHandlerBase*, 4> rws;
|
||||||
|
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit bd208038dd85a94dce8c763397ad5ac7eae76402
|
Subproject commit bdfe31dba48039b60fe700e7d03bfb95e9549688
|
2
generators/.gitignore
vendored
2
generators/.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
.~lock*
|
.~lock*
|
||||||
/venv
|
/venv
|
||||||
|
/.idea/*
|
||||||
|
!/.idea/runConfigurations
|
||||||
|
@ -84,6 +84,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
|||||||
10800;0x2a30;STORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
10800;0x2a30;STORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
10801;0x2a31;MSG_QUEUE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
10801;0x2a31;MSG_QUEUE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
|
10803;0x2a33;FILESTORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
|
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acsDefs.h
|
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acsDefs.h
|
||||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acsDefs.h
|
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acsDefs.h
|
||||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acsDefs.h
|
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acsDefs.h
|
||||||
@ -252,10 +254,11 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
|||||||
14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h
|
14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h
|
||||||
14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;bsp_q7s/core/CoreController.h
|
14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;bsp_q7s/core/CoreController.h
|
||||||
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
|
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
|
||||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
|
14100;0x3714;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/tmtc/PersistentTmStore.h
|
||||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
|
14200;0x3778;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14201;0x3779;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||||
14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14202;0x377a;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14203;0x377b;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14204;0x377c;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14205;0x377d;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
|
14206;0x377e;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
|
|
@ -104,6 +104,7 @@
|
|||||||
0x53000008;PUS_SERVICE_8_FUNCTION_MGMT
|
0x53000008;PUS_SERVICE_8_FUNCTION_MGMT
|
||||||
0x53000009;PUS_SERVICE_9_TIME_MGMT
|
0x53000009;PUS_SERVICE_9_TIME_MGMT
|
||||||
0x53000011;PUS_SERVICE_11_TC_SCHEDULER
|
0x53000011;PUS_SERVICE_11_TC_SCHEDULER
|
||||||
|
0x53000015;PUS_SERVICE_15_TM_STORAGE
|
||||||
0x53000017;PUS_SERVICE_17_TEST
|
0x53000017;PUS_SERVICE_17_TEST
|
||||||
0x53000020;PUS_SERVICE_20_PARAMETERS
|
0x53000020;PUS_SERVICE_20_PARAMETERS
|
||||||
0x53000200;PUS_SERVICE_200_MODE_MGMT
|
0x53000200;PUS_SERVICE_200_MODE_MGMT
|
||||||
@ -142,6 +143,11 @@
|
|||||||
0x73010002;PL_SUBSYSTEM
|
0x73010002;PL_SUBSYSTEM
|
||||||
0x73010003;TCS_SUBSYSTEM
|
0x73010003;TCS_SUBSYSTEM
|
||||||
0x73010004;COM_SUBSYSTEM
|
0x73010004;COM_SUBSYSTEM
|
||||||
|
0x73020001;MISC_TM_STORE
|
||||||
|
0x73020002;OK_TM_STORE
|
||||||
|
0x73020003;NOT_OK_TM_STORE
|
||||||
|
0x73020004;HK_TM_STORE
|
||||||
|
0x73030000;CFDP_TM_STORE
|
||||||
0x73500000;CCSDS_IP_CORE_BRIDGE
|
0x73500000;CCSDS_IP_CORE_BRIDGE
|
||||||
0x90000003;THERMAL_TEMP_INSERTER
|
0x90000003;THERMAL_TEMP_INSERTER
|
||||||
0xCAFECAFE;DUMMY_INTERFACE
|
0xCAFECAFE;DUMMY_INTERFACE
|
||||||
|
|
@ -49,16 +49,17 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
|||||||
0x4fa4;HEATER_MainSwitchSetTimeout;No description;164;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
0x4fa4;HEATER_MainSwitchSetTimeout;No description;164;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
||||||
0x4fa5;HEATER_CommandAlreadyWaiting;No description;165;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
0x4fa5;HEATER_CommandAlreadyWaiting;No description;165;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
||||||
0x60a0;CCSDS_CommandNotImplemented;Received action message with unknown action id;160;CCSDS_HANDLER;mission/tmtc/CcsdsIpCoreHandler.h
|
0x60a0;CCSDS_CommandNotImplemented;Received action message with unknown action id;160;CCSDS_HANDLER;mission/tmtc/CcsdsIpCoreHandler.h
|
||||||
0x6a01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
|
0x6b01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
|
||||||
0x6b01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
|
0x6c01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
|
||||||
0x6c01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
|
0x6d01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
|
||||||
0x6902;ACSKAL_KalmanUninitialized;No description;2;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6903;ACSKAL_KalmanNoGyrData;No description;3;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6904;ACSKAL_KalmanNoModelVectors;No description;4;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6905;ACSKAL_KalmanNoSusMgmStrData;No description;5;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a05;ACSMEKF_MekfNoSusMgmStrData;No description;5;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6906;ACSKAL_KalmanCovarianceInversionFailed;No description;6;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a06;ACSMEKF_MekfCovarianceInversionFailed;No description;6;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6907;ACSKAL_KalmanInitialized;No description;7;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a07;ACSMEKF_MekfInitialized;No description;7;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6908;ACSKAL_KalmanRunning;No description;8;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a08;ACSMEKF_MekfRunning;No description;8;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
|
0x6900;ACSCTRL_FileDeletionFailed;No description;0;ACS_CTRL;mission/controller/AcsController.h
|
||||||
0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
||||||
0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
||||||
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
||||||
|
|
@ -84,6 +84,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
|||||||
10800;0x2a30;STORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
10800;0x2a30;STORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
10801;0x2a31;MSG_QUEUE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
10801;0x2a31;MSG_QUEUE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
|
10803;0x2a33;FILESTORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
|
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acsDefs.h
|
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acsDefs.h
|
||||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acsDefs.h
|
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acsDefs.h
|
||||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acsDefs.h
|
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acsDefs.h
|
||||||
@ -252,10 +254,11 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
|||||||
14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h
|
14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h
|
||||||
14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;bsp_q7s/core/CoreController.h
|
14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;bsp_q7s/core/CoreController.h
|
||||||
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
|
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
|
||||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
|
14100;0x3714;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/tmtc/PersistentTmStore.h
|
||||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
|
14200;0x3778;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14201;0x3779;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||||
14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14202;0x377a;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14203;0x377b;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14204;0x377c;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
14205;0x377d;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
|
14206;0x377e;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||||
|
|
@ -102,6 +102,7 @@
|
|||||||
0x53000008;PUS_SERVICE_8_FUNCTION_MGMT
|
0x53000008;PUS_SERVICE_8_FUNCTION_MGMT
|
||||||
0x53000009;PUS_SERVICE_9_TIME_MGMT
|
0x53000009;PUS_SERVICE_9_TIME_MGMT
|
||||||
0x53000011;PUS_SERVICE_11_TC_SCHEDULER
|
0x53000011;PUS_SERVICE_11_TC_SCHEDULER
|
||||||
|
0x53000015;PUS_SERVICE_15_TM_STORAGE
|
||||||
0x53000017;PUS_SERVICE_17_TEST
|
0x53000017;PUS_SERVICE_17_TEST
|
||||||
0x53000020;PUS_SERVICE_20_PARAMETERS
|
0x53000020;PUS_SERVICE_20_PARAMETERS
|
||||||
0x53000200;PUS_SERVICE_200_MODE_MGMT
|
0x53000200;PUS_SERVICE_200_MODE_MGMT
|
||||||
@ -148,6 +149,11 @@
|
|||||||
0x73010002;PL_SUBSYSTEM
|
0x73010002;PL_SUBSYSTEM
|
||||||
0x73010003;TCS_SUBSYSTEM
|
0x73010003;TCS_SUBSYSTEM
|
||||||
0x73010004;COM_SUBSYSTEM
|
0x73010004;COM_SUBSYSTEM
|
||||||
|
0x73020001;MISC_TM_STORE
|
||||||
|
0x73020002;OK_TM_STORE
|
||||||
|
0x73020003;NOT_OK_TM_STORE
|
||||||
|
0x73020004;HK_TM_STORE
|
||||||
|
0x73030000;CFDP_TM_STORE
|
||||||
0x73500000;CCSDS_IP_CORE_BRIDGE
|
0x73500000;CCSDS_IP_CORE_BRIDGE
|
||||||
0x90000003;THERMAL_TEMP_INSERTER
|
0x90000003;THERMAL_TEMP_INSERTER
|
||||||
0xFFFFFFFF;NO_OBJECT
|
0xFFFFFFFF;NO_OBJECT
|
||||||
|
|
@ -49,16 +49,17 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
|||||||
0x4fa4;HEATER_MainSwitchSetTimeout;No description;164;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
0x4fa4;HEATER_MainSwitchSetTimeout;No description;164;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
||||||
0x4fa5;HEATER_CommandAlreadyWaiting;No description;165;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
0x4fa5;HEATER_CommandAlreadyWaiting;No description;165;HEATER_HANDLER;mission/devices/HeaterHandler.h
|
||||||
0x60a0;CCSDS_CommandNotImplemented;Received action message with unknown action id;160;CCSDS_HANDLER;mission/tmtc/CcsdsIpCoreHandler.h
|
0x60a0;CCSDS_CommandNotImplemented;Received action message with unknown action id;160;CCSDS_HANDLER;mission/tmtc/CcsdsIpCoreHandler.h
|
||||||
0x6a01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
|
0x6b01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
|
||||||
0x6b01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
|
0x6c01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
|
||||||
0x6c01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
|
0x6d01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
|
||||||
0x6902;ACSKAL_KalmanUninitialized;No description;2;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6903;ACSKAL_KalmanNoGyrData;No description;3;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6904;ACSKAL_KalmanNoModelVectors;No description;4;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6905;ACSKAL_KalmanNoSusMgmStrData;No description;5;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a05;ACSMEKF_MekfNoSusMgmStrData;No description;5;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6906;ACSKAL_KalmanCovarianceInversionFailed;No description;6;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a06;ACSMEKF_MekfCovarianceInversionFailed;No description;6;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6907;ACSKAL_KalmanInitialized;No description;7;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a07;ACSMEKF_MekfInitialized;No description;7;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
0x6908;ACSKAL_KalmanRunning;No description;8;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
|
0x6a08;ACSMEKF_MekfRunning;No description;8;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||||
|
0x6900;ACSCTRL_FileDeletionFailed;No description;0;ACS_CTRL;mission/controller/AcsController.h
|
||||||
0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
||||||
0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
||||||
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 260 translations.
|
* @brief Auto-generated event translation file. Contains 263 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-02-23 15:39:20
|
* Generated on: 2023-02-24 16:57:00
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -90,6 +90,8 @@ const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
|
|||||||
const char *STORE_ERROR_STRING = "STORE_ERROR";
|
const char *STORE_ERROR_STRING = "STORE_ERROR";
|
||||||
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
|
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
|
||||||
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
|
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
|
||||||
|
const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
|
||||||
|
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
|
||||||
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
||||||
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||||
@ -253,6 +255,7 @@ const char *REBOOT_HW_STRING = "REBOOT_HW";
|
|||||||
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
|
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
|
||||||
const char *VERSION_INFO_STRING = "VERSION_INFO";
|
const char *VERSION_INFO_STRING = "VERSION_INFO";
|
||||||
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
|
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
|
||||||
|
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||||
@ -433,6 +436,10 @@ const char *translateEvents(Event event) {
|
|||||||
return MSG_QUEUE_ERROR_STRING;
|
return MSG_QUEUE_ERROR_STRING;
|
||||||
case (10802):
|
case (10802):
|
||||||
return SERIALIZATION_ERROR_STRING;
|
return SERIALIZATION_ERROR_STRING;
|
||||||
|
case (10803):
|
||||||
|
return FILESTORE_ERROR_STRING;
|
||||||
|
case (10804):
|
||||||
|
return FILENAME_TOO_LARGE_ERROR_STRING;
|
||||||
case (11200):
|
case (11200):
|
||||||
return SAFE_RATE_VIOLATION_STRING;
|
return SAFE_RATE_VIOLATION_STRING;
|
||||||
case (11201):
|
case (11201):
|
||||||
@ -760,18 +767,20 @@ const char *translateEvents(Event event) {
|
|||||||
case (14006):
|
case (14006):
|
||||||
return CURRENT_IMAGE_INFO_STRING;
|
return CURRENT_IMAGE_INFO_STRING;
|
||||||
case (14100):
|
case (14100):
|
||||||
|
return POSSIBLE_FILE_CORRUPTION_STRING;
|
||||||
|
case (14200):
|
||||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||||
case (14101):
|
case (14201):
|
||||||
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
||||||
case (14102):
|
case (14202):
|
||||||
return SYRLINKS_OVERHEATING_STRING;
|
return SYRLINKS_OVERHEATING_STRING;
|
||||||
case (14103):
|
case (14203):
|
||||||
return PLOC_OVERHEATING_STRING;
|
return PLOC_OVERHEATING_STRING;
|
||||||
case (14104):
|
case (14204):
|
||||||
return OBC_OVERHEATING_STRING;
|
return OBC_OVERHEATING_STRING;
|
||||||
case (14105):
|
case (14205):
|
||||||
return HPA_OVERHEATING_STRING;
|
return HPA_OVERHEATING_STRING;
|
||||||
case (14106):
|
case (14206):
|
||||||
return PLPCDU_OVERHEATING_STRING;
|
return PLPCDU_OVERHEATING_STRING;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN_EVENT";
|
return "UNKNOWN_EVENT";
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 153 translations.
|
* Contains 159 translations.
|
||||||
* Generated on: 2023-02-23 15:39:20
|
* Generated on: 2023-02-24 16:57:00
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
@ -110,6 +110,7 @@ const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTIN
|
|||||||
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
|
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
|
||||||
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
|
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
|
||||||
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
|
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
|
||||||
|
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
|
||||||
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
|
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
|
||||||
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
|
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
|
||||||
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
|
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
|
||||||
@ -156,6 +157,11 @@ const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
|
|||||||
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
|
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
|
||||||
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
|
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
|
||||||
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
|
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
|
||||||
|
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
|
||||||
|
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
|
||||||
|
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
|
||||||
|
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
|
||||||
|
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
|
||||||
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
|
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
|
||||||
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
|
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
|
||||||
const char *NO_OBJECT_STRING = "NO_OBJECT";
|
const char *NO_OBJECT_STRING = "NO_OBJECT";
|
||||||
@ -370,6 +376,8 @@ const char *translateObject(object_id_t object) {
|
|||||||
return PUS_SERVICE_9_TIME_MGMT_STRING;
|
return PUS_SERVICE_9_TIME_MGMT_STRING;
|
||||||
case 0x53000011:
|
case 0x53000011:
|
||||||
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
|
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
|
||||||
|
case 0x53000015:
|
||||||
|
return PUS_SERVICE_15_TM_STORAGE_STRING;
|
||||||
case 0x53000017:
|
case 0x53000017:
|
||||||
return PUS_SERVICE_17_TEST_STRING;
|
return PUS_SERVICE_17_TEST_STRING;
|
||||||
case 0x53000020:
|
case 0x53000020:
|
||||||
@ -462,6 +470,16 @@ const char *translateObject(object_id_t object) {
|
|||||||
return TCS_SUBSYSTEM_STRING;
|
return TCS_SUBSYSTEM_STRING;
|
||||||
case 0x73010004:
|
case 0x73010004:
|
||||||
return COM_SUBSYSTEM_STRING;
|
return COM_SUBSYSTEM_STRING;
|
||||||
|
case 0x73020001:
|
||||||
|
return MISC_TM_STORE_STRING;
|
||||||
|
case 0x73020002:
|
||||||
|
return OK_TM_STORE_STRING;
|
||||||
|
case 0x73020003:
|
||||||
|
return NOT_OK_TM_STORE_STRING;
|
||||||
|
case 0x73020004:
|
||||||
|
return HK_TM_STORE_STRING;
|
||||||
|
case 0x73030000:
|
||||||
|
return CFDP_TM_STORE_STRING;
|
||||||
case 0x73500000:
|
case 0x73500000:
|
||||||
return CCSDS_IP_CORE_BRIDGE_STRING;
|
return CCSDS_IP_CORE_BRIDGE_STRING;
|
||||||
case 0x90000003:
|
case 0x90000003:
|
||||||
|
@ -172,20 +172,10 @@ bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
oneShotSwitches.gpsReadFailedSwitch = true;
|
oneShotSwitches.gpsReadFailedSwitch = true;
|
||||||
// did not event get mode, nothing to see.
|
ReturnValue_t result = handleGpsReadData();
|
||||||
if (MODE_SET != (MODE_SET & gps.set)) {
|
if (result == returnvalue::OK) {
|
||||||
if (mode != MODE_OFF) {
|
|
||||||
if (maxTimeToReachFix.hasTimedOut() and oneShotSwitches.cantGetFixSwitch) {
|
|
||||||
sif::warning
|
|
||||||
<< "GPSHyperionHandler::readGpsDataFromGpsd: No mode could be set in allowed "
|
|
||||||
<< maxTimeToReachFix.timeout / 1000 << " seconds" << std::endl;
|
|
||||||
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.timeout);
|
|
||||||
oneShotSwitches.cantGetFixSwitch = false;
|
|
||||||
}
|
|
||||||
// Mode is on, so do next read immediately
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
// GPS device is off anyway, so do other handling
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
noModeSetCntr = 0;
|
noModeSetCntr = 0;
|
||||||
@ -197,11 +187,26 @@ bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
|
|||||||
"SHM read not implemented"
|
"SHM read not implemented"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
handleGpsReadData();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
||||||
|
bool modeIsSet = true;
|
||||||
|
if (MODE_SET != (MODE_SET & gps.set)) {
|
||||||
|
if (mode != MODE_OFF) {
|
||||||
|
if (maxTimeToReachFix.hasTimedOut() and oneShotSwitches.cantGetFixSwitch) {
|
||||||
|
sif::warning << "GpsHyperionLinuxController: No mode could be set in allowed "
|
||||||
|
<< maxTimeToReachFix.timeout / 1000 << " seconds" << std::endl;
|
||||||
|
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.timeout);
|
||||||
|
oneShotSwitches.cantGetFixSwitch = false;
|
||||||
|
}
|
||||||
|
modeIsSet = false;
|
||||||
|
} else {
|
||||||
|
// GPS device is off anyway, so do other handling
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PoolReadGuard pg(&gpsSet);
|
PoolReadGuard pg(&gpsSet);
|
||||||
if (pg.getReadResult() != returnvalue::OK) {
|
if (pg.getReadResult() != returnvalue::OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
@ -211,6 +216,7 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool validFix = false;
|
bool validFix = false;
|
||||||
|
if (modeIsSet) {
|
||||||
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
|
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
|
||||||
if (gps.fix.mode == 2 or gps.fix.mode == 3) {
|
if (gps.fix.mode == 2 or gps.fix.mode == 3) {
|
||||||
validFix = true;
|
validFix = true;
|
||||||
@ -227,50 +233,76 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
|||||||
}
|
}
|
||||||
modeCommanded = false;
|
modeCommanded = false;
|
||||||
}
|
}
|
||||||
gpsSet.setValidity(false, true);
|
|
||||||
} else if (gps.satellites_used > 0 && validFix && mode != MODE_OFF) {
|
|
||||||
gpsSet.setValidity(true, true);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
gpsSet.fixMode.setValid(modeIsSet);
|
||||||
|
|
||||||
|
// Only set on specific messages, so only set a valid flag to invalid
|
||||||
|
// if not set for more than a full message set (10 messages here)
|
||||||
|
if (SATELLITE_SET == (SATELLITE_SET & gps.set)) {
|
||||||
gpsSet.satInUse.value = gps.satellites_used;
|
gpsSet.satInUse.value = gps.satellites_used;
|
||||||
gpsSet.satInView.value = gps.satellites_visible;
|
gpsSet.satInView.value = gps.satellites_visible;
|
||||||
|
if (not gpsSet.satInUse.isValid()) {
|
||||||
|
gpsSet.satInUse.setValid(true);
|
||||||
|
gpsSet.satInView.setValid(true);
|
||||||
|
}
|
||||||
|
satNotSetCounter = 0;
|
||||||
|
} else {
|
||||||
|
satNotSetCounter++;
|
||||||
|
if (gpsSet.satInUse.isValid() and satNotSetCounter >= 10) {
|
||||||
|
gpsSet.satInUse.setValid(false);
|
||||||
|
gpsSet.satInView.setValid(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LATLON is set for every message, no need for a counter
|
||||||
bool latValid = false;
|
bool latValid = false;
|
||||||
|
bool longValid = false;
|
||||||
|
if (LATLON_SET == (LATLON_SET & gps.set)) {
|
||||||
if (std::isfinite(gps.fix.latitude)) {
|
if (std::isfinite(gps.fix.latitude)) {
|
||||||
// Negative latitude -> South direction
|
// Negative latitude -> South direction
|
||||||
gpsSet.latitude.value = gps.fix.latitude;
|
gpsSet.latitude.value = gps.fix.latitude;
|
||||||
|
// As specified in gps.h: Only valid if mode >= 2
|
||||||
if (gps.fix.mode >= 2) {
|
if (gps.fix.mode >= 2) {
|
||||||
latValid = true;
|
latValid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gpsSet.latitude.setValid(latValid);
|
|
||||||
|
|
||||||
bool longValid = false;
|
|
||||||
if (std::isfinite(gps.fix.longitude)) {
|
if (std::isfinite(gps.fix.longitude)) {
|
||||||
// Negative longitude -> West direction
|
// Negative longitude -> West direction
|
||||||
gpsSet.longitude.value = gps.fix.longitude;
|
gpsSet.longitude.value = gps.fix.longitude;
|
||||||
|
// As specified in gps.h: Only valid if mode >= 2
|
||||||
if (gps.fix.mode >= 2) {
|
if (gps.fix.mode >= 2) {
|
||||||
longValid = true;
|
longValid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gpsSet.latitude.setValid(longValid);
|
}
|
||||||
|
gpsSet.latitude.setValid(latValid);
|
||||||
|
gpsSet.longitude.setValid(longValid);
|
||||||
|
|
||||||
|
// ALTITUDE is set for every message, no need for a counter
|
||||||
bool altitudeValid = false;
|
bool altitudeValid = false;
|
||||||
if (std::isfinite(gps.fix.altitude)) {
|
if (ALTITUDE_SET == (ALTITUDE_SET & gps.set) && std::isfinite(gps.fix.altitude)) {
|
||||||
gpsSet.altitude.value = gps.fix.altitude;
|
gpsSet.altitude.value = gps.fix.altitude;
|
||||||
|
// As specified in gps.h: Only valid if mode == 3
|
||||||
if (gps.fix.mode == 3) {
|
if (gps.fix.mode == 3) {
|
||||||
altitudeValid = true;
|
altitudeValid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gpsSet.altitude.setValid(altitudeValid);
|
gpsSet.altitude.setValid(altitudeValid);
|
||||||
|
|
||||||
if (std::isfinite(gps.fix.speed)) {
|
// SPEED is set for every message, no need for a counter
|
||||||
|
bool speedValid = false;
|
||||||
|
if (SPEED_SET == (SPEED_SET & gps.set) && std::isfinite(gps.fix.speed)) {
|
||||||
gpsSet.speed.value = gps.fix.speed;
|
gpsSet.speed.value = gps.fix.speed;
|
||||||
} else {
|
speedValid = true;
|
||||||
gpsSet.speed.setValid(false);
|
|
||||||
}
|
}
|
||||||
|
gpsSet.speed.setValid(speedValid);
|
||||||
|
|
||||||
|
// TIME is set for every message, no need for a counter
|
||||||
|
bool timeValid = false;
|
||||||
if (TIME_SET == (TIME_SET & gps.set)) {
|
if (TIME_SET == (TIME_SET & gps.set)) {
|
||||||
|
timeValid = true;
|
||||||
timeval time = {};
|
timeval time = {};
|
||||||
#if LIBGPS_VERSION_MINOR <= 17
|
#if LIBGPS_VERSION_MINOR <= 17
|
||||||
gpsSet.unixSeconds.value = std::floor(gps.fix.time);
|
gpsSet.unixSeconds.value = std::floor(gps.fix.time);
|
||||||
@ -294,15 +326,14 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
|||||||
gpsSet.hours = timeOfDay.hour;
|
gpsSet.hours = timeOfDay.hour;
|
||||||
gpsSet.minutes = timeOfDay.minute;
|
gpsSet.minutes = timeOfDay.minute;
|
||||||
gpsSet.seconds = timeOfDay.second;
|
gpsSet.seconds = timeOfDay.second;
|
||||||
} else {
|
|
||||||
gpsSet.unixSeconds.setValid(false);
|
|
||||||
gpsSet.year.setValid(false);
|
|
||||||
gpsSet.month.setValid(false);
|
|
||||||
gpsSet.day.setValid(false);
|
|
||||||
gpsSet.hours.setValid(false);
|
|
||||||
gpsSet.minutes.setValid(false);
|
|
||||||
gpsSet.seconds.setValid(false);
|
|
||||||
}
|
}
|
||||||
|
gpsSet.unixSeconds.setValid(timeValid);
|
||||||
|
gpsSet.year.setValid(timeValid);
|
||||||
|
gpsSet.month.setValid(timeValid);
|
||||||
|
gpsSet.day.setValid(timeValid);
|
||||||
|
gpsSet.hours.setValid(timeValid);
|
||||||
|
gpsSet.minutes.setValid(timeValid);
|
||||||
|
gpsSet.seconds.setValid(timeValid);
|
||||||
|
|
||||||
if (debugHyperionGps) {
|
if (debugHyperionGps) {
|
||||||
sif::info << "-- Hyperion GPS Data --" << std::endl;
|
sif::info << "-- Hyperion GPS Data --" << std::endl;
|
||||||
|
@ -61,6 +61,8 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
|
|||||||
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
|
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
|
||||||
bool modeCommanded = false;
|
bool modeCommanded = false;
|
||||||
bool timeInit = false;
|
bool timeInit = false;
|
||||||
|
uint8_t satNotSetCounter = 0;
|
||||||
|
|
||||||
#if OBSW_THREAD_TRACING == 1
|
#if OBSW_THREAD_TRACING == 1
|
||||||
uint32_t opCounter = 0;
|
uint32_t opCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1742,18 +1742,21 @@ ReturnValue_t PlocSupervisorHandler::createMramDumpFile() {
|
|||||||
std::string filename = "mram-dump--" + timeStamp + ".bin";
|
std::string filename = "mram-dump--" + timeStamp + ".bin";
|
||||||
|
|
||||||
#ifdef XIPHOS_Q7S
|
#ifdef XIPHOS_Q7S
|
||||||
std::string currentMountPrefix = sdcMan->getCurrentMountPrefix();
|
const char* currentMountPrefix = sdcMan->getCurrentMountPrefix();
|
||||||
#else
|
#else
|
||||||
std::string currentMountPrefix("/mnt/sd0");
|
const char* currentMountPrefix = "/mnt/sd0";
|
||||||
#endif /* BOARD_TE0720 == 0 */
|
#endif /* BOARD_TE0720 == 0 */
|
||||||
|
if (currentMountPrefix == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if path to PLOC directory exists
|
// Check if path to PLOC directory exists
|
||||||
if (not std::filesystem::exists(std::string(currentMountPrefix + "/" + supervisorFilePath))) {
|
if (not std::filesystem::exists(std::string(currentMountPrefix) + "/" + supervisorFilePath)) {
|
||||||
sif::warning << "PlocSupervisorHandler::createMramDumpFile: Supervisor path does not exist"
|
sif::warning << "PlocSupervisorHandler::createMramDumpFile: Supervisor path does not exist"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return result::PATH_DOES_NOT_EXIST;
|
return result::PATH_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
activeMramFile = currentMountPrefix + "/" + supervisorFilePath + "/" + filename;
|
activeMramFile = std::string(currentMountPrefix) + "/" + supervisorFilePath + "/" + filename;
|
||||||
// Create new file
|
// Create new file
|
||||||
std::ofstream file(activeMramFile, std::ios_base::out);
|
std::ofstream file(activeMramFile, std::ios_base::out);
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
//! When using the newlib nano library, C99 support for stdio facilities
|
//! When using the newlib nano library, C99 support for stdio facilities
|
||||||
//! will not be provided. This define should be set to 1 if this is the case.
|
//! will not be provided. This define should be set to 1 if this is the case.
|
||||||
#define FSFW_NO_C99_IO 1
|
#define FSFW_NO_C99_IO 0
|
||||||
|
|
||||||
//! Specify whether a special mode store is used for Subsystem components.
|
//! Specify whether a special mode store is used for Subsystem components.
|
||||||
#define FSFW_USE_MODESTORE 0
|
#define FSFW_USE_MODESTORE 0
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 260 translations.
|
* @brief Auto-generated event translation file. Contains 263 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-02-23 15:39:20
|
* Generated on: 2023-02-24 16:57:00
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -90,6 +90,8 @@ const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
|
|||||||
const char *STORE_ERROR_STRING = "STORE_ERROR";
|
const char *STORE_ERROR_STRING = "STORE_ERROR";
|
||||||
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
|
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
|
||||||
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
|
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
|
||||||
|
const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
|
||||||
|
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
|
||||||
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
||||||
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||||
@ -253,6 +255,7 @@ const char *REBOOT_HW_STRING = "REBOOT_HW";
|
|||||||
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
|
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
|
||||||
const char *VERSION_INFO_STRING = "VERSION_INFO";
|
const char *VERSION_INFO_STRING = "VERSION_INFO";
|
||||||
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
|
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
|
||||||
|
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||||
@ -433,6 +436,10 @@ const char *translateEvents(Event event) {
|
|||||||
return MSG_QUEUE_ERROR_STRING;
|
return MSG_QUEUE_ERROR_STRING;
|
||||||
case (10802):
|
case (10802):
|
||||||
return SERIALIZATION_ERROR_STRING;
|
return SERIALIZATION_ERROR_STRING;
|
||||||
|
case (10803):
|
||||||
|
return FILESTORE_ERROR_STRING;
|
||||||
|
case (10804):
|
||||||
|
return FILENAME_TOO_LARGE_ERROR_STRING;
|
||||||
case (11200):
|
case (11200):
|
||||||
return SAFE_RATE_VIOLATION_STRING;
|
return SAFE_RATE_VIOLATION_STRING;
|
||||||
case (11201):
|
case (11201):
|
||||||
@ -760,18 +767,20 @@ const char *translateEvents(Event event) {
|
|||||||
case (14006):
|
case (14006):
|
||||||
return CURRENT_IMAGE_INFO_STRING;
|
return CURRENT_IMAGE_INFO_STRING;
|
||||||
case (14100):
|
case (14100):
|
||||||
|
return POSSIBLE_FILE_CORRUPTION_STRING;
|
||||||
|
case (14200):
|
||||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||||
case (14101):
|
case (14201):
|
||||||
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
||||||
case (14102):
|
case (14202):
|
||||||
return SYRLINKS_OVERHEATING_STRING;
|
return SYRLINKS_OVERHEATING_STRING;
|
||||||
case (14103):
|
case (14203):
|
||||||
return PLOC_OVERHEATING_STRING;
|
return PLOC_OVERHEATING_STRING;
|
||||||
case (14104):
|
case (14204):
|
||||||
return OBC_OVERHEATING_STRING;
|
return OBC_OVERHEATING_STRING;
|
||||||
case (14105):
|
case (14205):
|
||||||
return HPA_OVERHEATING_STRING;
|
return HPA_OVERHEATING_STRING;
|
||||||
case (14106):
|
case (14206):
|
||||||
return PLPCDU_OVERHEATING_STRING;
|
return PLPCDU_OVERHEATING_STRING;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN_EVENT";
|
return "UNKNOWN_EVENT";
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 153 translations.
|
* Contains 159 translations.
|
||||||
* Generated on: 2023-02-23 15:39:20
|
* Generated on: 2023-02-24 16:57:00
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
@ -110,6 +110,7 @@ const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTIN
|
|||||||
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
|
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
|
||||||
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
|
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
|
||||||
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
|
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
|
||||||
|
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
|
||||||
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
|
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
|
||||||
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
|
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
|
||||||
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
|
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
|
||||||
@ -156,6 +157,11 @@ const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
|
|||||||
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
|
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
|
||||||
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
|
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
|
||||||
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
|
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
|
||||||
|
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
|
||||||
|
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
|
||||||
|
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
|
||||||
|
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
|
||||||
|
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
|
||||||
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
|
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
|
||||||
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
|
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
|
||||||
const char *NO_OBJECT_STRING = "NO_OBJECT";
|
const char *NO_OBJECT_STRING = "NO_OBJECT";
|
||||||
@ -370,6 +376,8 @@ const char *translateObject(object_id_t object) {
|
|||||||
return PUS_SERVICE_9_TIME_MGMT_STRING;
|
return PUS_SERVICE_9_TIME_MGMT_STRING;
|
||||||
case 0x53000011:
|
case 0x53000011:
|
||||||
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
|
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
|
||||||
|
case 0x53000015:
|
||||||
|
return PUS_SERVICE_15_TM_STORAGE_STRING;
|
||||||
case 0x53000017:
|
case 0x53000017:
|
||||||
return PUS_SERVICE_17_TEST_STRING;
|
return PUS_SERVICE_17_TEST_STRING;
|
||||||
case 0x53000020:
|
case 0x53000020:
|
||||||
@ -462,6 +470,16 @@ const char *translateObject(object_id_t object) {
|
|||||||
return TCS_SUBSYSTEM_STRING;
|
return TCS_SUBSYSTEM_STRING;
|
||||||
case 0x73010004:
|
case 0x73010004:
|
||||||
return COM_SUBSYSTEM_STRING;
|
return COM_SUBSYSTEM_STRING;
|
||||||
|
case 0x73020001:
|
||||||
|
return MISC_TM_STORE_STRING;
|
||||||
|
case 0x73020002:
|
||||||
|
return OK_TM_STORE_STRING;
|
||||||
|
case 0x73020003:
|
||||||
|
return NOT_OK_TM_STORE_STRING;
|
||||||
|
case 0x73020004:
|
||||||
|
return HK_TM_STORE_STRING;
|
||||||
|
case 0x73030000:
|
||||||
|
return CFDP_TM_STORE_STRING;
|
||||||
case 0x73500000:
|
case 0x73500000:
|
||||||
return CCSDS_IP_CORE_BRIDGE_STRING;
|
return CCSDS_IP_CORE_BRIDGE_STRING;
|
||||||
case 0x90000003:
|
case 0x90000003:
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#include "AcsController.h"
|
#include "AcsController.h"
|
||||||
|
|
||||||
#include <fsfw/datapool/PoolReadGuard.h>
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
|
#include <mission/acsDefs.h>
|
||||||
#include "mission/acsDefs.h"
|
#include <mission/config/torquer.h>
|
||||||
#include "mission/config/torquer.h"
|
|
||||||
|
|
||||||
AcsController::AcsController(object_id_t objectId)
|
AcsController::AcsController(object_id_t objectId)
|
||||||
: ExtendedControllerBase(objectId),
|
: ExtendedControllerBase(objectId),
|
||||||
@ -46,6 +45,26 @@ ReturnValue_t AcsController::handleCommandMessage(CommandMessage *message) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t AcsController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
|
const uint8_t *data, size_t size) {
|
||||||
|
switch (actionId) {
|
||||||
|
case SOLAR_ARRAY_DEPLOYMENT_SUCCESSFUL: {
|
||||||
|
ReturnValue_t result = guidance.solarArrayDeploymentComplete();
|
||||||
|
if (result == returnvalue::FAILED) {
|
||||||
|
return FILE_DELETION_FAILED;
|
||||||
|
}
|
||||||
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
|
}
|
||||||
|
case RESET_MEKF: {
|
||||||
|
navigation.resetMekf(&mekfData);
|
||||||
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return HasActionsIF::INVALID_ACTION_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MessageQueueId_t AcsController::getCommandQueue() const { return commandQueue->getId(); }
|
MessageQueueId_t AcsController::getCommandQueue() const { return commandQueue->getId(); }
|
||||||
|
|
||||||
ReturnValue_t AcsController::getParameter(uint8_t domainId, uint8_t parameterId,
|
ReturnValue_t AcsController::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||||
@ -60,6 +79,25 @@ void AcsController::performControlOperation() {
|
|||||||
#if OBSW_THREAD_TRACING == 1
|
#if OBSW_THREAD_TRACING == 1
|
||||||
trace::threadTrace(opCounter, "ACS & TCS PST");
|
trace::threadTrace(opCounter, "ACS & TCS PST");
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
PoolReadGuard pg(&mgmDataRaw);
|
||||||
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
|
copyMgmData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
PoolReadGuard pg(&susDataRaw);
|
||||||
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
|
copySusData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
PoolReadGuard pg(&gyrDataRaw);
|
||||||
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
|
copyGyrData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (internalState) {
|
switch (internalState) {
|
||||||
case InternalState::STARTUP: {
|
case InternalState::STARTUP: {
|
||||||
initialCountdown.resetTimer();
|
initialCountdown.resetTimer();
|
||||||
@ -95,25 +133,6 @@ void AcsController::performControlOperation() {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
PoolReadGuard pg(&mgmDataRaw);
|
|
||||||
if (pg.getReadResult() == returnvalue::OK) {
|
|
||||||
copyMgmData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
PoolReadGuard pg(&susDataRaw);
|
|
||||||
if (pg.getReadResult() == returnvalue::OK) {
|
|
||||||
copySusData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
PoolReadGuard pg(&gyrDataRaw);
|
|
||||||
if (pg.getReadResult() == returnvalue::OK) {
|
|
||||||
copyGyrData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AcsController::performSafe() {
|
void AcsController::performSafe() {
|
||||||
@ -124,8 +143,8 @@ void AcsController::performSafe() {
|
|||||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||||
&susDataProcessed, &mekfData);
|
&susDataProcessed, &mekfData);
|
||||||
if (result != MultiplicativeKalmanFilter::KALMAN_RUNNING &&
|
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||||
result != MultiplicativeKalmanFilter::KALMAN_INITIALIZED) {
|
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||||
if (not mekfInvalidFlag) {
|
if (not mekfInvalidFlag) {
|
||||||
triggerEvent(acs::MEKF_INVALID_INFO);
|
triggerEvent(acs::MEKF_INVALID_INFO);
|
||||||
mekfInvalidFlag = true;
|
mekfInvalidFlag = true;
|
||||||
@ -139,7 +158,7 @@ void AcsController::performSafe() {
|
|||||||
// if MEKF is working
|
// if MEKF is working
|
||||||
double magMomMtq[3] = {0, 0, 0}, errAng = 0.0;
|
double magMomMtq[3] = {0, 0, 0}, errAng = 0.0;
|
||||||
bool magMomMtqValid = false;
|
bool magMomMtqValid = false;
|
||||||
if (result == MultiplicativeKalmanFilter::KALMAN_RUNNING) {
|
if (result == MultiplicativeKalmanFilter::MEKF_RUNNING) {
|
||||||
safeCtrl.safeMekf(now, mekfData.quatMekf.value, mekfData.quatMekf.isValid(),
|
safeCtrl.safeMekf(now, mekfData.quatMekf.value, mekfData.quatMekf.isValid(),
|
||||||
mgmDataProcessed.magIgrfModel.value, mgmDataProcessed.magIgrfModel.isValid(),
|
mgmDataProcessed.magIgrfModel.value, mgmDataProcessed.magIgrfModel.isValid(),
|
||||||
susDataProcessed.sunIjkModel.value, susDataProcessed.isValid(),
|
susDataProcessed.sunIjkModel.value, susDataProcessed.isValid(),
|
||||||
@ -189,8 +208,8 @@ void AcsController::performDetumble() {
|
|||||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||||
&susDataProcessed, &mekfData);
|
&susDataProcessed, &mekfData);
|
||||||
if (result != MultiplicativeKalmanFilter::KALMAN_RUNNING &&
|
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||||
result != MultiplicativeKalmanFilter::KALMAN_INITIALIZED) {
|
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||||
if (not mekfInvalidFlag) {
|
if (not mekfInvalidFlag) {
|
||||||
triggerEvent(acs::MEKF_INVALID_INFO);
|
triggerEvent(acs::MEKF_INVALID_INFO);
|
||||||
mekfInvalidFlag = true;
|
mekfInvalidFlag = true;
|
||||||
@ -236,8 +255,8 @@ void AcsController::performPointingCtrl() {
|
|||||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||||
&susDataProcessed, &mekfData);
|
&susDataProcessed, &mekfData);
|
||||||
if (result != MultiplicativeKalmanFilter::KALMAN_RUNNING &&
|
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||||
result != MultiplicativeKalmanFilter::KALMAN_INITIALIZED) {
|
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||||
if (not mekfInvalidFlag) {
|
if (not mekfInvalidFlag) {
|
||||||
triggerEvent(acs::MEKF_INVALID_INFO);
|
triggerEvent(acs::MEKF_INVALID_INFO);
|
||||||
mekfInvalidFlag = true;
|
mekfInvalidFlag = true;
|
||||||
@ -246,9 +265,10 @@ void AcsController::performPointingCtrl() {
|
|||||||
triggerEvent(acs::MEKF_INVALID_MODE_VIOLATION);
|
triggerEvent(acs::MEKF_INVALID_MODE_VIOLATION);
|
||||||
}
|
}
|
||||||
mekfInvalidCounter++;
|
mekfInvalidCounter++;
|
||||||
commandActuators(0, 0, 0, acsParameters.magnetorquesParameter.torqueDuration, cmdSpeedRws[0],
|
// commandActuators(0, 0, 0, acsParameters.magnetorquesParameter.torqueDuration,
|
||||||
cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
|
// cmdSpeedRws[0],
|
||||||
acsParameters.rwHandlingParameters.rampTime);
|
// cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
|
||||||
|
// acsParameters.rwHandlingParameters.rampTime);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
mekfInvalidFlag = false;
|
mekfInvalidFlag = false;
|
||||||
@ -395,7 +415,7 @@ void AcsController::performPointingCtrl() {
|
|||||||
sensorValues.rw4Set.currSpeed.value, torqueRwsScaled, cmdSpeedRws);
|
sensorValues.rw4Set.currSpeed.value, torqueRwsScaled, cmdSpeedRws);
|
||||||
actuatorCmd.cmdDipolMtq(mgtDpDes, cmdDipolMtqs);
|
actuatorCmd.cmdDipolMtq(mgtDpDes, cmdDipolMtqs);
|
||||||
|
|
||||||
updateCtrlValData(targetQuat, errorQuat, errorAngle);
|
updateCtrlValData(targetQuat, errorQuat, errorAngle, targetSatRotRate);
|
||||||
updateActuatorCmdData(rwTrqNs, cmdSpeedRws, cmdDipolMtqs);
|
updateActuatorCmdData(rwTrqNs, cmdSpeedRws, cmdDipolMtqs);
|
||||||
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||||
// acsParameters.magnetorquesParameter.torqueDuration, cmdSpeedRws[0],
|
// acsParameters.magnetorquesParameter.torqueDuration, cmdSpeedRws[0],
|
||||||
@ -457,16 +477,20 @@ void AcsController::updateCtrlValData(double errAng) {
|
|||||||
ctrlValData.errQuat.setValid(false);
|
ctrlValData.errQuat.setValid(false);
|
||||||
ctrlValData.errAng.value = errAng;
|
ctrlValData.errAng.value = errAng;
|
||||||
ctrlValData.errAng.setValid(true);
|
ctrlValData.errAng.setValid(true);
|
||||||
|
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
ctrlValData.tgtRotRate.setValid(false);
|
||||||
ctrlValData.setValidity(true, false);
|
ctrlValData.setValidity(true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQuat, double errAng) {
|
void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQuat, double errAng,
|
||||||
|
const double *tgtRotRate) {
|
||||||
PoolReadGuard pg(&ctrlValData);
|
PoolReadGuard pg(&ctrlValData);
|
||||||
if (pg.getReadResult() == returnvalue::OK) {
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
std::memcpy(ctrlValData.tgtQuat.value, tgtQuat, 4 * sizeof(double));
|
std::memcpy(ctrlValData.tgtQuat.value, tgtQuat, 4 * sizeof(double));
|
||||||
std::memcpy(ctrlValData.errQuat.value, errQuat, 4 * sizeof(double));
|
std::memcpy(ctrlValData.errQuat.value, errQuat, 4 * sizeof(double));
|
||||||
ctrlValData.errAng.value = errAng;
|
ctrlValData.errAng.value = errAng;
|
||||||
|
std::memcpy(ctrlValData.tgtRotRate.value, tgtRotRate, 3 * sizeof(double));
|
||||||
ctrlValData.setValidity(true, true);
|
ctrlValData.setValidity(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -477,6 +501,7 @@ void AcsController::disableCtrlValData() {
|
|||||||
std::memcpy(ctrlValData.tgtQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
std::memcpy(ctrlValData.tgtQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
||||||
std::memcpy(ctrlValData.errQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
std::memcpy(ctrlValData.errQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
||||||
ctrlValData.errAng.value = 0;
|
ctrlValData.errAng.value = 0;
|
||||||
|
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
ctrlValData.setValidity(false, true);
|
ctrlValData.setValidity(false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
#ifndef MISSION_CONTROLLER_ACSCONTROLLER_H_
|
#ifndef MISSION_CONTROLLER_ACSCONTROLLER_H_
|
||||||
#define MISSION_CONTROLLER_ACSCONTROLLER_H_
|
#define MISSION_CONTROLLER_ACSCONTROLLER_H_
|
||||||
|
|
||||||
|
#include <eive/objects.h>
|
||||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||||
#include <fsfw/parameters/ParameterHelper.h>
|
#include <fsfw/parameters/ParameterHelper.h>
|
||||||
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
||||||
|
#include <fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h>
|
||||||
|
#include <fsfw_hal/devicehandlers/MgmRM3100Handler.h>
|
||||||
|
#include <mission/devices/devicedefinitions/SusDefinitions.h>
|
||||||
#include <mission/devices/devicedefinitions/imtqHelpers.h>
|
#include <mission/devices/devicedefinitions/imtqHelpers.h>
|
||||||
#include <mission/devices/devicedefinitions/rwHelpers.h>
|
#include <mission/devices/devicedefinitions/rwHelpers.h>
|
||||||
|
#include <mission/trace.h>
|
||||||
|
|
||||||
#include "acs/ActuatorCmd.h"
|
#include "acs/ActuatorCmd.h"
|
||||||
#include "acs/Guidance.h"
|
#include "acs/Guidance.h"
|
||||||
@ -17,11 +22,6 @@
|
|||||||
#include "acs/control/PtgCtrl.h"
|
#include "acs/control/PtgCtrl.h"
|
||||||
#include "acs/control/SafeCtrl.h"
|
#include "acs/control/SafeCtrl.h"
|
||||||
#include "controllerdefinitions/AcsCtrlDefinitions.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/SusDefinitions.h"
|
|
||||||
#include "mission/trace.h"
|
|
||||||
|
|
||||||
class AcsController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
class AcsController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
||||||
public:
|
public:
|
||||||
@ -41,6 +41,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr double UNIT_QUAT[4] = {0, 0, 0, 1};
|
static constexpr double UNIT_QUAT[4] = {0, 0, 0, 1};
|
||||||
|
static constexpr double ZERO_VEC[3] = {0, 0, 0};
|
||||||
static constexpr double RW_OFF_TORQUE[4] = {0.0, 0.0, 0.0, 0.0};
|
static constexpr double RW_OFF_TORQUE[4] = {0.0, 0.0, 0.0, 0.0};
|
||||||
static constexpr int32_t RW_OFF_SPEED[4] = {0, 0, 0, 0};
|
static constexpr int32_t RW_OFF_SPEED[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
|||||||
|
|
||||||
uint8_t detumbleCounter = 0;
|
uint8_t detumbleCounter = 0;
|
||||||
uint8_t multipleRwUnavailableCounter = 0;
|
uint8_t multipleRwUnavailableCounter = 0;
|
||||||
bool mekfInvalidFlag = true;
|
bool mekfInvalidFlag = false;
|
||||||
uint8_t mekfInvalidCounter = 0;
|
uint8_t mekfInvalidCounter = 0;
|
||||||
int32_t cmdSpeedRws[4] = {0, 0, 0, 0};
|
int32_t cmdSpeedRws[4] = {0, 0, 0, 0};
|
||||||
int16_t cmdDipolMtqs[3] = {0, 0, 0};
|
int16_t cmdDipolMtqs[3] = {0, 0, 0};
|
||||||
@ -68,13 +69,23 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum class InternalState { STARTUP, INITIAL_DELAY, READY };
|
enum class InternalState { STARTUP, INITIAL_DELAY, READY };
|
||||||
|
|
||||||
InternalState internalState = InternalState::STARTUP;
|
InternalState internalState = InternalState::STARTUP;
|
||||||
|
|
||||||
|
/** Device command IDs */
|
||||||
|
static const DeviceCommandId_t SOLAR_ARRAY_DEPLOYMENT_SUCCESSFUL = 0x0;
|
||||||
|
static const DeviceCommandId_t RESET_MEKF = 0x1;
|
||||||
|
|
||||||
|
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_CTRL;
|
||||||
|
static constexpr ReturnValue_t FILE_DELETION_FAILED = MAKE_RETURN_CODE(0);
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||||
void performControlOperation() override;
|
void performControlOperation() override;
|
||||||
|
|
||||||
|
/* HasActionsIF overrides */
|
||||||
|
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
|
const uint8_t* data, size_t size) override;
|
||||||
|
|
||||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
LocalDataPoolManager& poolManager) override;
|
LocalDataPoolManager& poolManager) override;
|
||||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||||
@ -92,7 +103,8 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
|||||||
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
|
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
|
||||||
const int16_t* mtqTargetDipole);
|
const int16_t* mtqTargetDipole);
|
||||||
void updateCtrlValData(double errAng);
|
void updateCtrlValData(double errAng);
|
||||||
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng);
|
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
|
||||||
|
const double* tgtRotRate);
|
||||||
void disableCtrlValData();
|
void disableCtrlValData();
|
||||||
|
|
||||||
/* ACS Sensor Values */
|
/* ACS Sensor Values */
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
/*******************************
|
|
||||||
* EIVE Flight Software Framework (FSFW)
|
|
||||||
* (c) 2022 IRS, Uni Stuttgart
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
#ifndef ACSPARAMETERS_H_
|
#ifndef ACSPARAMETERS_H_
|
||||||
#define ACSPARAMETERS_H_
|
#define ACSPARAMETERS_H_
|
||||||
|
|
||||||
|
@ -551,3 +551,19 @@ void Guidance::getTargetParamsSafe(double sunTargetSafe[3], double satRateSafe[3
|
|||||||
std::memcpy(satRateSafe, acsParameters.safeModeControllerParameters.satRateRef,
|
std::memcpy(satRateSafe, acsParameters.safeModeControllerParameters.satRateRef,
|
||||||
3 * sizeof(double));
|
3 * sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Guidance::solarArrayDeploymentComplete() {
|
||||||
|
if (std::filesystem::exists(SD_0_SKEWED_PTG_FILE)) {
|
||||||
|
std::remove(SD_0_SKEWED_PTG_FILE);
|
||||||
|
if (std::filesystem::exists(SD_0_SKEWED_PTG_FILE)) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (std::filesystem::exists(SD_1_SKEWED_PTG_FILE)) {
|
||||||
|
std::remove(SD_1_SKEWED_PTG_FILE);
|
||||||
|
if (std::filesystem::exists(SD_1_SKEWED_PTG_FILE)) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ class Guidance {
|
|||||||
virtual ~Guidance();
|
virtual ~Guidance();
|
||||||
|
|
||||||
void getTargetParamsSafe(double sunTargetSafe[3], double satRateRef[3]);
|
void getTargetParamsSafe(double sunTargetSafe[3], double satRateRef[3]);
|
||||||
|
ReturnValue_t solarArrayDeploymentComplete();
|
||||||
|
|
||||||
// Function to get the target quaternion and refence rotation rate from gps position and
|
// Function to get the target quaternion and refence rotation rate from gps position and
|
||||||
// position of the ground station
|
// position of the ground station
|
||||||
|
@ -189,12 +189,12 @@ ReturnValue_t MultiplicativeKalmanFilter::init(
|
|||||||
initialCovarianceMatrix[5][4] = initGyroCov[2][1];
|
initialCovarianceMatrix[5][4] = initGyroCov[2][1];
|
||||||
initialCovarianceMatrix[5][5] = initGyroCov[2][2];
|
initialCovarianceMatrix[5][5] = initGyroCov[2][2];
|
||||||
updateDataSetWithoutData(mekfData, MekfStatus::INITIALIZED);
|
updateDataSetWithoutData(mekfData, MekfStatus::INITIALIZED);
|
||||||
return KALMAN_INITIALIZED;
|
return MEKF_INITIALIZED;
|
||||||
} else {
|
} else {
|
||||||
// no initialisation possible, no valid measurements
|
// no initialisation possible, no valid measurements
|
||||||
validInit = false;
|
validInit = false;
|
||||||
updateDataSetWithoutData(mekfData, MekfStatus::UNINITIALIZED);
|
updateDataSetWithoutData(mekfData, MekfStatus::UNINITIALIZED);
|
||||||
return KALMAN_UNINITIALIZED;
|
return MEKF_UNINITIALIZED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,12 +211,12 @@ ReturnValue_t MultiplicativeKalmanFilter::mekfEst(const double *quaternionSTR, c
|
|||||||
int MDF = 0; // Matrix Dimension Factor
|
int MDF = 0; // Matrix Dimension Factor
|
||||||
if (!validGYRs_) {
|
if (!validGYRs_) {
|
||||||
updateDataSetWithoutData(mekfData, MekfStatus::NO_GYR_DATA);
|
updateDataSetWithoutData(mekfData, MekfStatus::NO_GYR_DATA);
|
||||||
return KALMAN_NO_GYR_DATA;
|
return MEKF_NO_GYR_DATA;
|
||||||
}
|
}
|
||||||
// Check for Model Calculations
|
// Check for Model Calculations
|
||||||
else if (!validSSModel || !validMagModel) {
|
else if (!validSSModel || !validMagModel) {
|
||||||
updateDataSetWithoutData(mekfData, MekfStatus::NO_MODEL_VECTORS);
|
updateDataSetWithoutData(mekfData, MekfStatus::NO_MODEL_VECTORS);
|
||||||
return KALMAN_NO_MODEL_VECTORS;
|
return MEKF_NO_MODEL_VECTORS;
|
||||||
}
|
}
|
||||||
// Check Measurements available from SS, MAG, STR
|
// Check Measurements available from SS, MAG, STR
|
||||||
if (validSS && validMagField_ && validSTR_) {
|
if (validSS && validMagField_ && validSTR_) {
|
||||||
@ -854,7 +854,7 @@ ReturnValue_t MultiplicativeKalmanFilter::mekfEst(const double *quaternionSTR, c
|
|||||||
int inversionFailed = MathOperations<double>::inverseMatrix(*residualCov, *invResidualCov, MDF);
|
int inversionFailed = MathOperations<double>::inverseMatrix(*residualCov, *invResidualCov, MDF);
|
||||||
if (inversionFailed) {
|
if (inversionFailed) {
|
||||||
updateDataSetWithoutData(mekfData, MekfStatus::COVARIANCE_INVERSION_FAILED);
|
updateDataSetWithoutData(mekfData, MekfStatus::COVARIANCE_INVERSION_FAILED);
|
||||||
return KALMAN_COVARIANCE_INVERSION_FAILED; // RETURN VALUE ? -- Like: Kalman Inversion Failed
|
return MEKF_COVARIANCE_INVERSION_FAILED; // RETURN VALUE ? -- Like: Kalman Inversion Failed
|
||||||
}
|
}
|
||||||
|
|
||||||
// [K = P * H' / (H * P * H' + R)]
|
// [K = P * H' / (H * P * H' + R)]
|
||||||
@ -1085,16 +1085,17 @@ ReturnValue_t MultiplicativeKalmanFilter::mekfEst(const double *quaternionSTR, c
|
|||||||
MatrixOperations<double>::add(*cov0, *cov1, *initialCovarianceMatrix, 6, 6);
|
MatrixOperations<double>::add(*cov0, *cov1, *initialCovarianceMatrix, 6, 6);
|
||||||
|
|
||||||
updateDataSet(mekfData, MekfStatus::RUNNING, quatBJ, rotRateEst);
|
updateDataSet(mekfData, MekfStatus::RUNNING, quatBJ, rotRateEst);
|
||||||
return KALMAN_RUNNING;
|
return MEKF_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplicativeKalmanFilter::reset(acsctrl::MekfData *mekfData) {
|
ReturnValue_t MultiplicativeKalmanFilter::reset(acsctrl::MekfData *mekfData) {
|
||||||
double resetQuaternion[4] = {0, 0, 0, 1};
|
double resetQuaternion[4] = {0, 0, 0, 1};
|
||||||
double resetCovarianceMatrix[6][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
double resetCovarianceMatrix[6][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
||||||
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}};
|
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}};
|
||||||
std::memcpy(initialQuaternion, resetQuaternion, 4 * sizeof(double));
|
std::memcpy(initialQuaternion, resetQuaternion, 4 * sizeof(double));
|
||||||
std::memcpy(initialCovarianceMatrix, resetCovarianceMatrix, 6 * 6 * sizeof(double));
|
std::memcpy(initialCovarianceMatrix, resetCovarianceMatrix, 6 * 6 * sizeof(double));
|
||||||
updateDataSetWithoutData(mekfData, MekfStatus::UNINITIALIZED);
|
updateDataSetWithoutData(mekfData, MekfStatus::UNINITIALIZED);
|
||||||
|
return MEKF_UNINITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplicativeKalmanFilter::updateDataSetWithoutData(acsctrl::MekfData *mekfData,
|
void MultiplicativeKalmanFilter::updateDataSetWithoutData(acsctrl::MekfData *mekfData,
|
||||||
|
@ -1,17 +1,3 @@
|
|||||||
/*
|
|
||||||
* MultiplicativeKalmanFilter.h
|
|
||||||
*
|
|
||||||
* Created on: 4 Feb 2022
|
|
||||||
* Author: Robin Marquardt
|
|
||||||
*
|
|
||||||
* @brief: This class handles the calculation of an estimated quaternion and the gyro bias by
|
|
||||||
* means of the spacecraft attitude sensors
|
|
||||||
*
|
|
||||||
* @note: A description of the used algorithms can be found in the bachelor thesis of Robin
|
|
||||||
* Marquardt
|
|
||||||
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_Studenten/Marquardt_Robin&openfile=500811
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MULTIPLICATIVEKALMANFILTER_H_
|
#ifndef MULTIPLICATIVEKALMANFILTER_H_
|
||||||
#define MULTIPLICATIVEKALMANFILTER_H_
|
#define MULTIPLICATIVEKALMANFILTER_H_
|
||||||
|
|
||||||
@ -22,6 +8,13 @@
|
|||||||
#include "eive/resultClassIds.h"
|
#include "eive/resultClassIds.h"
|
||||||
|
|
||||||
class MultiplicativeKalmanFilter {
|
class MultiplicativeKalmanFilter {
|
||||||
|
/* @brief: This class handles the calculation of an estimated quaternion and the gyro bias by
|
||||||
|
* means of the spacecraft attitude sensors
|
||||||
|
*
|
||||||
|
* @note: A description of the used algorithms can be found in the bachelor thesis of Robin
|
||||||
|
* Marquardt
|
||||||
|
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_Studenten/Marquardt_Robin&openfile=500811
|
||||||
|
*/
|
||||||
public:
|
public:
|
||||||
/* @brief: Constructor
|
/* @brief: Constructor
|
||||||
* @param: acsParameters_ Pointer to object which defines the ACS configuration parameters
|
* @param: acsParameters_ Pointer to object which defines the ACS configuration parameters
|
||||||
@ -29,7 +22,7 @@ class MultiplicativeKalmanFilter {
|
|||||||
MultiplicativeKalmanFilter(AcsParameters *acsParameters_);
|
MultiplicativeKalmanFilter(AcsParameters *acsParameters_);
|
||||||
virtual ~MultiplicativeKalmanFilter();
|
virtual ~MultiplicativeKalmanFilter();
|
||||||
|
|
||||||
void reset(acsctrl::MekfData *mekfData);
|
ReturnValue_t reset(acsctrl::MekfData *mekfData);
|
||||||
|
|
||||||
/* @brief: init() - This function initializes the Kalman Filter and will provide the first
|
/* @brief: init() - This function initializes the Kalman Filter and will provide the first
|
||||||
* quaternion through the QUEST algorithm
|
* quaternion through the QUEST algorithm
|
||||||
@ -74,15 +67,15 @@ class MultiplicativeKalmanFilter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// resetting Mekf
|
// resetting Mekf
|
||||||
static constexpr uint8_t IF_KAL_ID = CLASS_ID::ACS_KALMAN;
|
static constexpr uint8_t IF_MEKF_ID = CLASS_ID::ACS_MEKF;
|
||||||
static constexpr ReturnValue_t KALMAN_UNINITIALIZED = returnvalue::makeCode(IF_KAL_ID, 2);
|
static constexpr ReturnValue_t MEKF_UNINITIALIZED = returnvalue::makeCode(IF_MEKF_ID, 2);
|
||||||
static constexpr ReturnValue_t KALMAN_NO_GYR_DATA = returnvalue::makeCode(IF_KAL_ID, 3);
|
static constexpr ReturnValue_t MEKF_NO_GYR_DATA = returnvalue::makeCode(IF_MEKF_ID, 3);
|
||||||
static constexpr ReturnValue_t KALMAN_NO_MODEL_VECTORS = returnvalue::makeCode(IF_KAL_ID, 4);
|
static constexpr ReturnValue_t MEKF_NO_MODEL_VECTORS = returnvalue::makeCode(IF_MEKF_ID, 4);
|
||||||
static constexpr ReturnValue_t KALMAN_NO_SUS_MGM_STR_DATA = returnvalue::makeCode(IF_KAL_ID, 5);
|
static constexpr ReturnValue_t MEKF_NO_SUS_MGM_STR_DATA = returnvalue::makeCode(IF_MEKF_ID, 5);
|
||||||
static constexpr ReturnValue_t KALMAN_COVARIANCE_INVERSION_FAILED =
|
static constexpr ReturnValue_t MEKF_COVARIANCE_INVERSION_FAILED =
|
||||||
returnvalue::makeCode(IF_KAL_ID, 6);
|
returnvalue::makeCode(IF_MEKF_ID, 6);
|
||||||
static constexpr ReturnValue_t KALMAN_INITIALIZED = returnvalue::makeCode(IF_KAL_ID, 7);
|
static constexpr ReturnValue_t MEKF_INITIALIZED = returnvalue::makeCode(IF_MEKF_ID, 7);
|
||||||
static constexpr ReturnValue_t KALMAN_RUNNING = returnvalue::makeCode(IF_KAL_ID, 8);
|
static constexpr ReturnValue_t MEKF_RUNNING = returnvalue::makeCode(IF_MEKF_ID, 8);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*Parameters*/
|
/*Parameters*/
|
||||||
|
@ -25,26 +25,25 @@ ReturnValue_t Navigation::useMekf(ACS::SensorValues *sensorValues,
|
|||||||
sensorValues->strSet.caliQy.isValid() &&
|
sensorValues->strSet.caliQy.isValid() &&
|
||||||
sensorValues->strSet.caliQz.isValid() && sensorValues->strSet.caliQw.isValid();
|
sensorValues->strSet.caliQz.isValid() && sensorValues->strSet.caliQw.isValid();
|
||||||
|
|
||||||
if (kalmanInit) {
|
if (mekfStatus == MultiplicativeKalmanFilter::MEKF_UNINITIALIZED) {
|
||||||
return multiplicativeKalmanFilter.mekfEst(
|
mekfStatus = multiplicativeKalmanFilter.init(
|
||||||
|
mgmDataProcessed->mgmVecTot.value, mgmDataProcessed->mgmVecTot.isValid(),
|
||||||
|
susDataProcessed->susVecTot.value, susDataProcessed->susVecTot.isValid(),
|
||||||
|
susDataProcessed->sunIjkModel.value, susDataProcessed->sunIjkModel.isValid(),
|
||||||
|
mgmDataProcessed->magIgrfModel.value, mgmDataProcessed->magIgrfModel.isValid(), mekfData);
|
||||||
|
return mekfStatus;
|
||||||
|
} else {
|
||||||
|
mekfStatus = multiplicativeKalmanFilter.mekfEst(
|
||||||
quatIB, quatIBValid, gyrDataProcessed->gyrVecTot.value,
|
quatIB, quatIBValid, gyrDataProcessed->gyrVecTot.value,
|
||||||
gyrDataProcessed->gyrVecTot.isValid(), mgmDataProcessed->mgmVecTot.value,
|
gyrDataProcessed->gyrVecTot.isValid(), mgmDataProcessed->mgmVecTot.value,
|
||||||
mgmDataProcessed->mgmVecTot.isValid(), susDataProcessed->susVecTot.value,
|
mgmDataProcessed->mgmVecTot.isValid(), susDataProcessed->susVecTot.value,
|
||||||
susDataProcessed->susVecTot.isValid(), susDataProcessed->sunIjkModel.value,
|
susDataProcessed->susVecTot.isValid(), susDataProcessed->sunIjkModel.value,
|
||||||
susDataProcessed->sunIjkModel.isValid(), mgmDataProcessed->magIgrfModel.value,
|
susDataProcessed->sunIjkModel.isValid(), mgmDataProcessed->magIgrfModel.value,
|
||||||
mgmDataProcessed->magIgrfModel.isValid(), acsParameters.onBoardParams.sampleTime, mekfData);
|
mgmDataProcessed->magIgrfModel.isValid(), acsParameters.onBoardParams.sampleTime, mekfData);
|
||||||
} else {
|
return mekfStatus;
|
||||||
ReturnValue_t result;
|
|
||||||
result = multiplicativeKalmanFilter.init(
|
|
||||||
mgmDataProcessed->mgmVecTot.value, mgmDataProcessed->mgmVecTot.isValid(),
|
|
||||||
susDataProcessed->susVecTot.value, susDataProcessed->susVecTot.isValid(),
|
|
||||||
susDataProcessed->sunIjkModel.value, susDataProcessed->sunIjkModel.isValid(),
|
|
||||||
mgmDataProcessed->magIgrfModel.value, mgmDataProcessed->magIgrfModel.isValid(), mekfData);
|
|
||||||
kalmanInit = true;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Navigation::resetMekf(acsctrl::MekfData *mekfData) {
|
void Navigation::resetMekf(acsctrl::MekfData *mekfData) {
|
||||||
multiplicativeKalmanFilter.reset(mekfData);
|
mekfStatus = multiplicativeKalmanFilter.reset(mekfData);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ class Navigation {
|
|||||||
private:
|
private:
|
||||||
MultiplicativeKalmanFilter multiplicativeKalmanFilter;
|
MultiplicativeKalmanFilter multiplicativeKalmanFilter;
|
||||||
AcsParameters acsParameters;
|
AcsParameters acsParameters;
|
||||||
bool kalmanInit = false;
|
ReturnValue_t mekfStatus = MultiplicativeKalmanFilter::MEKF_UNINITIALIZED;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ACS_NAVIGATION_H_ */
|
#endif /* ACS_NAVIGATION_H_ */
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
/*******************************
|
|
||||||
* EIVE Flight Software
|
|
||||||
* (c) 2022 IRS, Uni Stuttgart
|
|
||||||
*******************************/
|
|
||||||
#ifndef SENSORPROCESSING_H_
|
#ifndef SENSORPROCESSING_H_
|
||||||
#define SENSORPROCESSING_H_
|
#define SENSORPROCESSING_H_
|
||||||
|
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* SensorValues.cpp
|
|
||||||
*
|
|
||||||
* Created on: 30 Mar 2022
|
|
||||||
* Author: rooob
|
|
||||||
*/
|
|
||||||
#include "SensorValues.h"
|
#include "SensorValues.h"
|
||||||
|
|
||||||
#include <fsfw/datapool/PoolReadGuard.h>
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
/*
|
|
||||||
* SusConverter.cpp
|
|
||||||
*
|
|
||||||
* Created on: 17.01.2022
|
|
||||||
* Author: Timon Schwarz
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SusConverter.h"
|
#include "SusConverter.h"
|
||||||
|
|
||||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||||
#include <fsfw/datapoollocal/LocalPoolVector.h>
|
#include <fsfw/datapoollocal/LocalPoolVector.h>
|
||||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||||
#include <math.h> //for atan2
|
#include <math.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
* SusConverter.h
|
|
||||||
*
|
|
||||||
* Created on: Sep 22, 2022
|
|
||||||
* Author: marius
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
#ifndef MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
||||||
#define MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
#define MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
||||||
|
|
||||||
@ -28,8 +21,6 @@ class SusConverter {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
float alphaBetaRaw[2]; //[°]
|
float alphaBetaRaw[2]; //[°]
|
||||||
// float coeffAlpha[9][10];
|
|
||||||
// float coeffBeta[9][10];
|
|
||||||
float alphaBetaCalibrated[2]; //[°]
|
float alphaBetaCalibrated[2]; //[°]
|
||||||
float sunVectorSensorFrame[3]; //[-]
|
float sunVectorSensorFrame[3]; //[-]
|
||||||
|
|
||||||
|
@ -300,6 +300,7 @@ class MathOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static float matrixDeterminant(const T1 *inputMatrix, uint8_t size) {
|
static float matrixDeterminant(const T1 *inputMatrix, uint8_t size) {
|
||||||
|
/* do not use this. takes 300ms */
|
||||||
float det = 0;
|
float det = 0;
|
||||||
T1 matrix[size][size], submatrix[size - 1][size - 1];
|
T1 matrix[size][size], submatrix[size - 1][size - 1];
|
||||||
for (uint8_t row = 0; row < size; row++) {
|
for (uint8_t row = 0; row < size; row++) {
|
||||||
@ -329,9 +330,7 @@ class MathOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int inverseMatrix(const T1 *inputMatrix, T1 *inverse, uint8_t size) {
|
static int inverseMatrix(const T1 *inputMatrix, T1 *inverse, uint8_t size) {
|
||||||
if (MathOperations<T1>::matrixDeterminant(inputMatrix, size) == 0) {
|
// Stopwatch stopwatch;
|
||||||
return 1; // Matrix is singular and not invertible
|
|
||||||
}
|
|
||||||
T1 matrix[size][size], identity[size][size];
|
T1 matrix[size][size], identity[size][size];
|
||||||
// reformat array to matrix
|
// reformat array to matrix
|
||||||
for (uint8_t row = 0; row < size; row++) {
|
for (uint8_t row = 0; row < size; row++) {
|
||||||
@ -346,7 +345,6 @@ class MathOperations {
|
|||||||
}
|
}
|
||||||
// gauss-jordan algo
|
// gauss-jordan algo
|
||||||
// sort matrix such as no diag entry shall be 0
|
// sort matrix such as no diag entry shall be 0
|
||||||
// should not be needed as such a matrix has a det=0
|
|
||||||
for (uint8_t row = 0; row < size; row++) {
|
for (uint8_t row = 0; row < size; row++) {
|
||||||
if (matrix[row][row] == 0.0) {
|
if (matrix[row][row] == 0.0) {
|
||||||
bool swaped = false;
|
bool swaped = false;
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
// TCP server includes
|
// TCP server includes
|
||||||
#include "fsfw/osal/common/TcpTmTcBridge.h"
|
#include "fsfw/osal/common/TcpTmTcBridge.h"
|
||||||
#include "fsfw/osal/common/TcpTmTcServer.h"
|
#include "fsfw/osal/common/TcpTmTcServer.h"
|
||||||
|
#include "mission/tmtc/Service15TmStorage.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ EiveFaultHandler EIVE_FAULT_HANDLER;
|
|||||||
} // namespace cfdp
|
} // namespace cfdp
|
||||||
|
|
||||||
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
|
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
|
||||||
CfdpTmFunnel** cfdpFunnel) {
|
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan) {
|
||||||
// Framework objects
|
// Framework objects
|
||||||
new EventManager(objects::EVENT_MANAGER);
|
new EventManager(objects::EVENT_MANAGER);
|
||||||
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
|
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
|
||||||
@ -95,6 +96,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
|
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
|
||||||
StorageManagerIF* tcStore;
|
StorageManagerIF* tcStore;
|
||||||
StorageManagerIF* tmStore;
|
StorageManagerIF* tmStore;
|
||||||
|
StorageManagerIF* ipcStore;
|
||||||
{
|
{
|
||||||
PoolManager::LocalPoolConfig poolCfg = {{250, 16}, {250, 32}, {250, 64},
|
PoolManager::LocalPoolConfig poolCfg = {{250, 16}, {250, 32}, {250, 64},
|
||||||
{150, 128}, {120, 1024}, {120, 2048}};
|
{150, 128}, {120, 1024}, {120, 2048}};
|
||||||
@ -109,8 +111,8 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
|
|
||||||
{
|
{
|
||||||
PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {200, 32}, {150, 64}, {150, 128},
|
PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {200, 32}, {150, 64}, {150, 128},
|
||||||
{100, 256}, {50, 512}, {50, 1024}, {50, 2048}};
|
{100, 256}, {50, 512}, {50, 1024}, {10, 2048}};
|
||||||
new PoolManager(objects::IPC_STORE, poolCfg);
|
ipcStore = new PoolManager(objects::IPC_STORE, poolCfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OBSW_ADD_TCPIP_SERVERS == 1
|
#if OBSW_ADD_TCPIP_SERVERS == 1
|
||||||
@ -137,9 +139,11 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
new CcsdsDistributor(config::EIVE_PUS_APID, objects::CCSDS_PACKET_DISTRIBUTOR);
|
new CcsdsDistributor(config::EIVE_PUS_APID, objects::CCSDS_PACKET_DISTRIBUTOR);
|
||||||
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
|
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
|
||||||
|
|
||||||
*cfdpFunnel = new CfdpTmFunnel(objects::CFDP_TM_FUNNEL, config::EIVE_CFDP_APID, *tmStore, 50);
|
PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, *tmStore, *ipcStore, 50);
|
||||||
*pusFunnel = new PusTmFunnel(objects::PUS_TM_FUNNEL, *timeStamper, *tmStore,
|
*cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, config::EIVE_CFDP_APID);
|
||||||
|
PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, *tmStore, *ipcStore,
|
||||||
config::MAX_PUS_FUNNEL_QUEUE_DEPTH);
|
config::MAX_PUS_FUNNEL_QUEUE_DEPTH);
|
||||||
|
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *timeStamper, sdcMan);
|
||||||
#if OBSW_ADD_TCPIP_SERVERS == 1
|
#if OBSW_ADD_TCPIP_SERVERS == 1
|
||||||
#if OBSW_ADD_TMTC_UDP_SERVER == 1
|
#if OBSW_ADD_TMTC_UDP_SERVER == 1
|
||||||
(*cfdpFunnel)->addDestination("UDP Server", *udpBridge, 0);
|
(*cfdpFunnel)->addDestination("UDP Server", *udpBridge, 0);
|
||||||
@ -171,6 +175,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
new Service11TelecommandScheduling<common::OBSW_MAX_SCHEDULED_TCS>(
|
new Service11TelecommandScheduling<common::OBSW_MAX_SCHEDULED_TCS>(
|
||||||
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, config::EIVE_PUS_APID, pus::PUS_SERVICE_11),
|
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, config::EIVE_PUS_APID, pus::PUS_SERVICE_11),
|
||||||
ccsdsDistrib);
|
ccsdsDistrib);
|
||||||
|
new Service15TmStorage(objects::PUS_SERVICE_15_TM_STORAGE, config::EIVE_PUS_APID, 10);
|
||||||
new Service17Test(
|
new Service17Test(
|
||||||
PsbParams(objects::PUS_SERVICE_17_TEST, config::EIVE_PUS_APID, pus::PUS_SERVICE_17));
|
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,
|
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, config::EIVE_PUS_APID,
|
||||||
@ -232,7 +237,7 @@ void ObjectFactory::createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t the
|
|||||||
std::array<object_id_t, 4> rwIds) {
|
std::array<object_id_t, 4> rwIds) {
|
||||||
RwHelper rwHelper(rwIds);
|
RwHelper rwHelper(rwIds);
|
||||||
auto* rwAss = new RwAssembly(objects::RW_ASS, &pwrSwitcher, theSwitch, rwHelper);
|
auto* rwAss = new RwAssembly(objects::RW_ASS, &pwrSwitcher, theSwitch, rwHelper);
|
||||||
for (uint8_t idx = 0; idx < rwIds.size(); idx++) {
|
for (size_t idx = 0; idx < rwIds.size(); idx++) {
|
||||||
ReturnValue_t result = rws[idx]->connectModeTreeParent(*rwAss);
|
ReturnValue_t result = rws[idx]->connectModeTreeParent(*rwAss);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::error << "Connecting RW " << static_cast<int>(idx) << " to RW assembly failed"
|
sif::error << "Connecting RW " << static_cast<int>(idx) << " to RW assembly failed"
|
||||||
@ -251,7 +256,7 @@ void ObjectFactory::createSusAssy(PowerSwitchIF& pwrSwitcher,
|
|||||||
objects::SUS_6_R_LOC_XFYBZM_PT_XF, objects::SUS_7_R_LOC_XBYBZM_PT_XB,
|
objects::SUS_6_R_LOC_XFYBZM_PT_XF, objects::SUS_7_R_LOC_XBYBZM_PT_XB,
|
||||||
objects::SUS_8_R_LOC_XBYBZB_PT_YB, objects::SUS_9_R_LOC_XBYBZB_PT_YF,
|
objects::SUS_8_R_LOC_XBYBZB_PT_YB, objects::SUS_9_R_LOC_XBYBZB_PT_YF,
|
||||||
objects::SUS_10_N_LOC_XMYBZF_PT_ZF, objects::SUS_11_R_LOC_XBYMZB_PT_ZB};
|
objects::SUS_10_N_LOC_XMYBZF_PT_ZF, objects::SUS_11_R_LOC_XBYMZB_PT_ZB};
|
||||||
SusAssHelper susAssHelper = SusAssHelper(susIds);
|
auto susAssHelper = SusAssHelper(susIds);
|
||||||
auto susAss = new SusAssembly(objects::SUS_BOARD_ASS, &pwrSwitcher, susAssHelper);
|
auto susAss = new SusAssembly(objects::SUS_BOARD_ASS, &pwrSwitcher, susAssHelper);
|
||||||
for (auto& sus : suses) {
|
for (auto& sus : suses) {
|
||||||
if (sus != nullptr) {
|
if (sus != nullptr) {
|
||||||
@ -287,8 +292,8 @@ void ObjectFactory::createAcsBoardAssy(PowerSwitchIF& pwrSwitcher,
|
|||||||
|
|
||||||
TcsBoardAssembly* ObjectFactory::createTcsBoardAssy(PowerSwitchIF& pwrSwitcher) {
|
TcsBoardAssembly* ObjectFactory::createTcsBoardAssy(PowerSwitchIF& pwrSwitcher) {
|
||||||
TcsBoardHelper helper(RTD_INFOS);
|
TcsBoardHelper helper(RTD_INFOS);
|
||||||
TcsBoardAssembly* tcsBoardAss = new TcsBoardAssembly(
|
auto* tcsBoardAss = new TcsBoardAssembly(objects::TCS_BOARD_ASS, &pwrSwitcher,
|
||||||
objects::TCS_BOARD_ASS, &pwrSwitcher, pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper);
|
pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper);
|
||||||
tcsBoardAss->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
tcsBoardAss->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||||
return tcsBoardAss;
|
return tcsBoardAss;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define MISSION_CORE_GENERICFACTORY_H_
|
#define MISSION_CORE_GENERICFACTORY_H_
|
||||||
|
|
||||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||||
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||||
#include "fsfw/power/PowerSwitchIF.h"
|
#include "fsfw/power/PowerSwitchIF.h"
|
||||||
@ -37,7 +38,7 @@ const std::array<std::pair<object_id_t, std::string>, EiveMax31855::NUM_RTDS> RT
|
|||||||
namespace ObjectFactory {
|
namespace ObjectFactory {
|
||||||
|
|
||||||
void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
|
void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
|
||||||
CfdpTmFunnel** cfdpFunnel);
|
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan);
|
||||||
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
|
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
|
||||||
HeaterHandler*& heaterHandler);
|
HeaterHandler*& heaterHandler);
|
||||||
|
|
||||||
|
@ -517,6 +517,9 @@ void PayloadPcduHandler::checkJsonFileInit() {
|
|||||||
if (not jsonFileInitComplete) {
|
if (not jsonFileInitComplete) {
|
||||||
auto activeSd = sdcMan->getActiveSdCard();
|
auto activeSd = sdcMan->getActiveSdCard();
|
||||||
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
|
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
|
||||||
|
if (sdcMan->getCurrentMountPrefix() == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
params.initialize(sdcMan->getCurrentMountPrefix());
|
params.initialize(sdcMan->getCurrentMountPrefix());
|
||||||
jsonFileInitComplete = true;
|
jsonFileInitComplete = true;
|
||||||
}
|
}
|
||||||
|
@ -214,6 +214,9 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
|||||||
fileId = date_time_string();
|
fileId = date_time_string();
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
auto prefix = sdcMan.getCurrentMountPrefix();
|
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||||
|
if (prefix == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
||||||
fileName = oss.str();
|
fileName = oss.str();
|
||||||
ofstream out(fileName, ofstream::binary);
|
ofstream out(fileName, ofstream::binary);
|
||||||
@ -234,6 +237,9 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
|||||||
fileId = date_time_string();
|
fileId = date_time_string();
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
auto prefix = sdcMan.getCurrentMountPrefix();
|
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||||
|
if (prefix == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
||||||
fileName = oss.str();
|
fileName = oss.str();
|
||||||
fileNameSet = true;
|
fileNameSet = true;
|
||||||
@ -310,6 +316,16 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScexDeviceHandler::performOperationHook() {
|
void ScexDeviceHandler::performOperationHook() {
|
||||||
|
auto mntPrefix = sdcMan.getCurrentMountPrefix();
|
||||||
|
if (mntPrefix != nullptr) {
|
||||||
|
std::filesystem::path fullFilePath = mntPrefix;
|
||||||
|
fullFilePath /= "scex";
|
||||||
|
bool fileExists = std::filesystem::exists(fullFilePath);
|
||||||
|
|
||||||
|
if (not fileExists) {
|
||||||
|
std::filesystem::create_directory(fullFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
|
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
|
||||||
if (commandActive and finishCountdown.hasTimedOut()) {
|
if (commandActive and finishCountdown.hasTimedOut()) {
|
||||||
triggerEvent(scex::EXPERIMENT_TIMEDOUT, currCmd, 0);
|
triggerEvent(scex::EXPERIMENT_TIMEDOUT, currCmd, 0);
|
||||||
@ -373,13 +389,5 @@ void ScexDeviceHandler::setPowerSwitcher(PowerSwitchIF& powerSwitcher, power::Sw
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ScexDeviceHandler::initializeAfterTaskCreation() {
|
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();
|
return DeviceHandlerBase::initializeAfterTaskCreation();
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ class GpsPrimaryDataset : public StaticLocalDataSet<18> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GpsHyperionLinuxController;
|
friend class GpsHyperionLinuxController;
|
||||||
|
friend class GpsCtrlDummy;
|
||||||
GpsPrimaryDataset(HasLocalDataPoolIF* hkOwner)
|
GpsPrimaryDataset(HasLocalDataPoolIF* hkOwner)
|
||||||
: StaticLocalDataSet(hkOwner, GpsHyperion::DATASET_ID) {}
|
: StaticLocalDataSet(hkOwner, GpsHyperion::DATASET_ID) {}
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
class SdCardMountedIF {
|
class SdCardMountedIF {
|
||||||
public:
|
public:
|
||||||
virtual ~SdCardMountedIF(){};
|
virtual ~SdCardMountedIF(){};
|
||||||
virtual const std::string& getCurrentMountPrefix() const = 0;
|
virtual const char* getCurrentMountPrefix() const = 0;
|
||||||
virtual bool isSdCardUsable(std::optional<sd::SdCard> sdCard) = 0;
|
virtual bool isSdCardUsable(std::optional<sd::SdCard> sdCard) = 0;
|
||||||
virtual std::optional<sd::SdCard> getPreferredSdCard() const = 0;
|
virtual std::optional<sd::SdCard> getPreferredSdCard() const = 0;
|
||||||
virtual void setActiveSdCard(sd::SdCard sdCard) = 0;
|
virtual void setActiveSdCard(sd::SdCard sdCard) = 0;
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
target_sources(
|
target_sources(
|
||||||
${LIB_EIVE_MISSION}
|
${LIB_EIVE_MISSION}
|
||||||
PRIVATE CcsdsIpCoreHandler.cpp VirtualChannel.cpp TmFunnelHandler.cpp
|
PRIVATE CcsdsIpCoreHandler.cpp
|
||||||
TmFunnelBase.cpp CfdpTmFunnel.cpp PusTmFunnel.cpp)
|
VirtualChannel.cpp
|
||||||
|
TmFunnelHandler.cpp
|
||||||
|
TmFunnelBase.cpp
|
||||||
|
CfdpTmFunnel.cpp
|
||||||
|
Service15TmStorage.cpp
|
||||||
|
PersistentTmStore.cpp
|
||||||
|
PusTmFunnel.cpp)
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
|
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
|
||||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||||
|
|
||||||
CfdpTmFunnel::CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid,
|
CfdpTmFunnel::CfdpTmFunnel(TmFunnelBase::FunnelCfg cfg, uint16_t cfdpInCcsdsApid)
|
||||||
StorageManagerIF& tmStore, uint32_t messageDepth)
|
: TmFunnelBase(cfg), cfdpInCcsdsApid(cfdpInCcsdsApid) {}
|
||||||
: TmFunnelBase(objectId, tmStore, messageDepth), cfdpInCcsdsApid(cfdpInCcsdsApid) {}
|
|
||||||
|
|
||||||
const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }
|
const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
|
|
||||||
class CfdpTmFunnel : public TmFunnelBase {
|
class CfdpTmFunnel : public TmFunnelBase {
|
||||||
public:
|
public:
|
||||||
CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid, StorageManagerIF& tmStore,
|
CfdpTmFunnel(TmFunnelBase::FunnelCfg cfg, uint16_t cfdpInCcsdsApid);
|
||||||
uint32_t messageDepth);
|
|
||||||
[[nodiscard]] const char* getName() const override;
|
[[nodiscard]] const char* getName() const override;
|
||||||
ReturnValue_t performOperation(uint8_t opCode);
|
ReturnValue_t performOperation(uint8_t opCode);
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
|
362
mission/tmtc/PersistentTmStore.cpp
Normal file
362
mission/tmtc/PersistentTmStore.cpp
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
#include "PersistentTmStore.h"
|
||||||
|
|
||||||
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "fsfw/ipc/CommandMessage.h"
|
||||||
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
|
#include "fsfw/tmstorage/TmStoreMessage.h"
|
||||||
|
|
||||||
|
using namespace returnvalue;
|
||||||
|
|
||||||
|
PersistentTmStore::PersistentTmStore(object_id_t objectId, const char* baseDir,
|
||||||
|
std::string baseName, RolloverInterval intervalUnit,
|
||||||
|
uint32_t intervalCount, StorageManagerIF& tmStore,
|
||||||
|
SdCardMountedIF& sdcMan)
|
||||||
|
: SystemObject(objectId),
|
||||||
|
baseDir(baseDir),
|
||||||
|
baseName(std::move(baseName)),
|
||||||
|
sdcMan(sdcMan),
|
||||||
|
tmStore(tmStore) {
|
||||||
|
tcQueue = QueueFactory::instance()->createMessageQueue();
|
||||||
|
calcDiffSeconds(intervalUnit, intervalCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
for (auto const& file : directory_iterator(basePath)) {
|
||||||
|
if (file.is_directory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto pathStr = file.path().string();
|
||||||
|
if (pathStr.find(baseName) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unsigned int underscorePos = pathStr.find_last_of('_');
|
||||||
|
std::string stampStr = pathStr.substr(underscorePos + 1);
|
||||||
|
struct tm time {};
|
||||||
|
if (nullptr == strptime(stampStr.c_str(), FILE_DATE_FORMAT, &time)) {
|
||||||
|
sif::error << "PersistentTmStore::assignOrCreateMostRecentFile: Error reading timestamp"
|
||||||
|
<< std::endl;
|
||||||
|
// Delete the file and re-create it.
|
||||||
|
activeFile = std::nullopt;
|
||||||
|
std::filesystem::remove(file.path());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
time_t fileEpoch = timegm(&time);
|
||||||
|
// There is still a file within the active time window, so re-use that file for new TMs to
|
||||||
|
// store.
|
||||||
|
if (fileEpoch + static_cast<time_t>(rolloverDiffSeconds) > currentTv.tv_sec) {
|
||||||
|
activeFileTv.tv_sec = fileEpoch;
|
||||||
|
activeFile = file.path();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not activeFile.has_value()) {
|
||||||
|
return createMostRecentFile(std::nullopt);
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
|
||||||
|
TmFunnelBase& tmFunnel) {
|
||||||
|
CommandMessage cmdMessage;
|
||||||
|
ReturnValue_t result = tcQueue->receiveMessage(&cmdMessage);
|
||||||
|
if (result == MessageQueueIF::EMPTY) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (cmdMessage.getMessageType() == messagetypes::TM_STORE) {
|
||||||
|
Command_t cmd = cmdMessage.getCommand();
|
||||||
|
if (cmd == TmStoreMessage::DELETE_STORE_CONTENT_TIME) {
|
||||||
|
Clock::getClock_timeval(¤tTv);
|
||||||
|
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||||
|
auto accessor = ipcStore.getData(storeId);
|
||||||
|
uint32_t deleteUpToUnixSeconds = 0;
|
||||||
|
size_t size = accessor.second.size();
|
||||||
|
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, accessor.second.data(), &size,
|
||||||
|
SerializeIF::Endianness::NETWORK);
|
||||||
|
deleteUpTo(deleteUpToUnixSeconds);
|
||||||
|
} else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
|
||||||
|
Clock::getClock_timeval(¤tTv);
|
||||||
|
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||||
|
auto accessor = ipcStore.getData(storeId);
|
||||||
|
if (accessor.second.size() < 8) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
uint32_t dumpFromUnixSeconds;
|
||||||
|
uint32_t dumpUntilUnixSeconds;
|
||||||
|
size_t size = 8;
|
||||||
|
SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size,
|
||||||
|
SerializeIF::Endianness::NETWORK);
|
||||||
|
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
|
||||||
|
SerializeIF::Endianness::NETWORK);
|
||||||
|
dumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds, tmFunnel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::passPacket(PusTmReader& reader) {
|
||||||
|
bool inApidList = false;
|
||||||
|
if (filter.apid) {
|
||||||
|
auto& apidFilter = filter.apid.value();
|
||||||
|
if (std::find(apidFilter.begin(), apidFilter.end(), reader.getApid()) != apidFilter.end()) {
|
||||||
|
if (not filter.serviceSubservices and not filter.services) {
|
||||||
|
return storePacket(reader);
|
||||||
|
}
|
||||||
|
inApidList = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::pair<uint8_t, uint8_t> serviceSubservice;
|
||||||
|
serviceSubservice.first = reader.getService();
|
||||||
|
serviceSubservice.second = reader.getSubService();
|
||||||
|
if (filter.services) {
|
||||||
|
auto& serviceFilter = filter.services.value();
|
||||||
|
if (std::find(serviceFilter.begin(), serviceFilter.end(), serviceSubservice.first) !=
|
||||||
|
serviceFilter.end()) {
|
||||||
|
if (filter.apid and inApidList) {
|
||||||
|
return storePacket(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filter.serviceSubservices) {
|
||||||
|
auto& serviceSubserviceFilter = filter.serviceSubservices.value();
|
||||||
|
if (std::find(serviceSubserviceFilter.begin(), serviceSubserviceFilter.end(),
|
||||||
|
serviceSubservice) != serviceSubserviceFilter.end()) {
|
||||||
|
if (filter.apid and inApidList) {
|
||||||
|
return storePacket(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersistentTmStore::dumpFrom(uint32_t fromUnixSeconds, TmFunnelBase& tmFunnel) {
|
||||||
|
return dumpFromUpTo(fromUnixSeconds, currentTv.tv_sec, tmFunnel);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::storePacket(PusTmReader& reader) {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
if (baseDirUninitialized) {
|
||||||
|
updateBaseDir();
|
||||||
|
}
|
||||||
|
Clock::getClock_timeval(¤tTv);
|
||||||
|
// It is assumed here that the filesystem is usable.
|
||||||
|
if (not activeFile.has_value()) {
|
||||||
|
ReturnValue_t result = assignAndOrCreateMostRecentFile();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createNewFile = false;
|
||||||
|
std::optional<uint8_t> suffix = std::nullopt;
|
||||||
|
if (currentTv.tv_sec > activeFileTv.tv_sec + static_cast<int>(rolloverDiffSeconds)) {
|
||||||
|
createNewFile = true;
|
||||||
|
currentSameSecNumber = 0;
|
||||||
|
} else if (file_size(activeFile.value()) + reader.getFullPacketLen() > fileBuf.size()) {
|
||||||
|
createNewFile = true;
|
||||||
|
if (currentSameSecNumber >= MAX_FILES_IN_ONE_SECOND) {
|
||||||
|
currentSameSecNumber = 0;
|
||||||
|
}
|
||||||
|
if (currentTv.tv_sec == activeFileTv.tv_sec) {
|
||||||
|
suffix = currentSameSecNumber++;
|
||||||
|
} else {
|
||||||
|
currentSameSecNumber = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (createNewFile) {
|
||||||
|
createMostRecentFile(suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rollover conditions were handled, write to file now
|
||||||
|
std::ofstream of(activeFile.value(), std::ios::app | std::ios::binary);
|
||||||
|
of.write(reinterpret_cast<const char*>(reader.getFullData()),
|
||||||
|
static_cast<std::streamsize>(reader.getFullPacketLen()));
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t PersistentTmStore::getCommandQueue() const { return tcQueue->getId(); }
|
||||||
|
|
||||||
|
void PersistentTmStore::calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount) {
|
||||||
|
if (intervalUnit == RolloverInterval::MINUTELY) {
|
||||||
|
rolloverDiffSeconds = 60 * intervalCount;
|
||||||
|
} else if (intervalUnit == RolloverInterval::HOURLY) {
|
||||||
|
rolloverDiffSeconds = 60 * 60 * intervalCount;
|
||||||
|
} else if (intervalUnit == RolloverInterval::DAILY) {
|
||||||
|
rolloverDiffSeconds = 60 * 60 * 24 * intervalCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PersistentTmStore::updateBaseDir() {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
const char* currentPrefix = sdcMan.getCurrentMountPrefix();
|
||||||
|
if (currentPrefix == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
basePath = path(currentPrefix) / baseDir / baseName;
|
||||||
|
if (not exists(basePath)) {
|
||||||
|
create_directories(basePath);
|
||||||
|
}
|
||||||
|
baseDirUninitialized = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersistentTmStore::addApid(uint16_t apid) {
|
||||||
|
if (not filter.apid) {
|
||||||
|
filter.apid = std::vector<uint16_t>({apid});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filter.apid.value().push_back(apid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersistentTmStore::addService(uint8_t service) {
|
||||||
|
if (not filter.services) {
|
||||||
|
filter.services = std::vector<uint8_t>({service});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filter.services.value().push_back(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersistentTmStore::addServiceSubservice(uint8_t service, uint8_t subservice) {
|
||||||
|
if (not filter.serviceSubservices) {
|
||||||
|
filter.serviceSubservices =
|
||||||
|
std::vector<std::pair<uint8_t, uint8_t>>({std::pair(service, subservice)});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filter.serviceSubservices.value().emplace_back(service, subservice);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
for (auto const& file : directory_iterator(basePath)) {
|
||||||
|
if (file.is_directory() or (activeFile.has_value() and (activeFile.value() == file.path()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Convert file time to the UNIX epoch
|
||||||
|
struct tm fileTime {};
|
||||||
|
if (pathToTm(file.path(), fileTime) != returnvalue::OK) {
|
||||||
|
sif::error << "Time extraction for " << file << "failed" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
time_t fileEpoch = timegm(&fileTime);
|
||||||
|
if (fileEpoch + rolloverDiffSeconds < unixSeconds) {
|
||||||
|
std::filesystem::remove(file.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersistentTmStore::dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds,
|
||||||
|
TmFunnelBase& funnel) {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
for (auto const& file : directory_iterator(basePath)) {
|
||||||
|
if (file.is_directory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
struct tm fileTime {};
|
||||||
|
if (pathToTm(file.path(), fileTime) != returnvalue::OK) {
|
||||||
|
sif::error << "Time extraction for file " << file << "failed" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
|
||||||
|
if ((fileEpoch > fromUnixSeconds) and (fileEpoch + rolloverDiffSeconds <= upToUnixSeconds)) {
|
||||||
|
fileToPackets(file, fileEpoch, funnel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::pathToTm(const std::filesystem::path& path, struct tm& time) {
|
||||||
|
auto pathStr = path.string();
|
||||||
|
size_t splitChar = pathStr.find('_');
|
||||||
|
auto timeOnlyStr = pathStr.substr(splitChar + 1);
|
||||||
|
if (nullptr == strptime(timeOnlyStr.c_str(), FILE_DATE_FORMAT, &time)) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersistentTmStore::fileToPackets(const std::filesystem::path& path, uint32_t unixStamp,
|
||||||
|
TmFunnelBase& funnel) {
|
||||||
|
store_address_t storeId;
|
||||||
|
TmTcMessage message;
|
||||||
|
size_t size = std::filesystem::file_size(path);
|
||||||
|
if (size < 6) {
|
||||||
|
// Can't even read the CCSDS header
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::ifstream ifile(path, std::ios::binary);
|
||||||
|
ifile.read(reinterpret_cast<char*>(fileBuf.data()), static_cast<std::streamsize>(size));
|
||||||
|
size_t currentIdx = 0;
|
||||||
|
while (currentIdx < size) {
|
||||||
|
PusTmReader reader(&timeReader, fileBuf.data(), fileBuf.size());
|
||||||
|
// CRC check to fully ensure this is a valid TM
|
||||||
|
ReturnValue_t result = reader.parseDataWithCrcCheck();
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
result = tmStore.addData(&storeId, fileBuf.data() + currentIdx, reader.getFullPacketLen());
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
funnel.sendPacketToDestinations(storeId, message, fileBuf.data() + currentIdx,
|
||||||
|
reader.getFullPacketLen());
|
||||||
|
currentIdx += reader.getFullPacketLen();
|
||||||
|
} else {
|
||||||
|
sif::error << "Parsing of PUS TM failed with code " << result << std::endl;
|
||||||
|
triggerEvent(POSSIBLE_FILE_CORRUPTION, result, unixStamp);
|
||||||
|
// Stop for now, do not really know where to continue and we do not trust the file anymore.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::createMostRecentFile(std::optional<uint8_t> suffix) {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
unsigned currentIdx = 0;
|
||||||
|
path pathStart = basePath / baseName;
|
||||||
|
memcpy(fileBuf.data() + currentIdx, pathStart.c_str(), pathStart.string().length());
|
||||||
|
currentIdx += pathStart.string().length();
|
||||||
|
fileBuf[currentIdx] = '_';
|
||||||
|
currentIdx += 1;
|
||||||
|
time_t epoch = currentTv.tv_sec;
|
||||||
|
struct tm* time = gmtime(&epoch);
|
||||||
|
size_t writtenBytes = strftime(reinterpret_cast<char*>(fileBuf.data() + currentIdx),
|
||||||
|
fileBuf.size(), FILE_DATE_FORMAT, time);
|
||||||
|
if (writtenBytes == 0) {
|
||||||
|
sif::error << "PersistentTmStore::createMostRecentFile: Could not create file timestamp"
|
||||||
|
<< std::endl;
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
currentIdx += writtenBytes;
|
||||||
|
char* res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), ".bin");
|
||||||
|
if (res == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
currentIdx += 4;
|
||||||
|
if (suffix.has_value()) {
|
||||||
|
std::string fullSuffix = "." + std::to_string(suffix.value());
|
||||||
|
res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), fullSuffix.c_str());
|
||||||
|
if (res == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
currentIdx += fullSuffix.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
path newPath(std::string(reinterpret_cast<const char*>(fileBuf.data()), currentIdx));
|
||||||
|
std::ofstream of(newPath, std::ios::binary);
|
||||||
|
activeFile = newPath;
|
||||||
|
activeFileTv = currentTv;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::initializeTmStore() {
|
||||||
|
Clock::getClock_timeval(¤tTv);
|
||||||
|
updateBaseDir();
|
||||||
|
return assignAndOrCreateMostRecentFile();
|
||||||
|
}
|
87
mission/tmtc/PersistentTmStore.h
Normal file
87
mission/tmtc/PersistentTmStore.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#ifndef MISSION_TMTC_TMSTOREBACKEND_H_
|
||||||
|
#define MISSION_TMTC_TMSTOREBACKEND_H_
|
||||||
|
|
||||||
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
|
#include <fsfw/timemanager/CdsShortTimeStamper.h>
|
||||||
|
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
||||||
|
#include <fsfw/tmtcpacket/pus/tm/PusTmReader.h>
|
||||||
|
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "TmFunnelBase.h"
|
||||||
|
#include "eive/eventSubsystemIds.h"
|
||||||
|
|
||||||
|
struct PacketFilter {
|
||||||
|
std::optional<std::vector<uint16_t>> apid;
|
||||||
|
std::optional<std::vector<uint8_t>> services;
|
||||||
|
std::optional<std::vector<std::pair<uint8_t, uint8_t>>> serviceSubservices;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RolloverInterval { MINUTELY, HOURLY, DAILY };
|
||||||
|
|
||||||
|
class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
||||||
|
public:
|
||||||
|
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PERSISTENT_TM_STORE;
|
||||||
|
|
||||||
|
//! [EXPORT] : [COMMENT]
|
||||||
|
//! P1: Result code of TM packet parser.
|
||||||
|
//! P2: Timestamp of possibly corrupt file as a unix timestamp.
|
||||||
|
static constexpr Event POSSIBLE_FILE_CORRUPTION =
|
||||||
|
event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
|
||||||
|
PersistentTmStore(object_id_t objectId, const char* baseDir, std::string baseName,
|
||||||
|
RolloverInterval intervalUnit, uint32_t intervalCount,
|
||||||
|
StorageManagerIF& tmStore, SdCardMountedIF& sdcMan);
|
||||||
|
|
||||||
|
ReturnValue_t initializeTmStore();
|
||||||
|
ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, TmFunnelBase& tmFunnel);
|
||||||
|
|
||||||
|
void addApid(uint16_t apid);
|
||||||
|
void addService(uint8_t service);
|
||||||
|
void addServiceSubservice(uint8_t service, uint8_t subservice);
|
||||||
|
|
||||||
|
void deleteUpTo(uint32_t unixSeconds);
|
||||||
|
void dumpFrom(uint32_t fromUnixSeconds, TmFunnelBase& tmFunnel);
|
||||||
|
void dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds, TmFunnelBase& tmFunnel);
|
||||||
|
|
||||||
|
ReturnValue_t passPacket(PusTmReader& reader);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr uint8_t MAX_FILES_IN_ONE_SECOND = 10;
|
||||||
|
static constexpr size_t MAX_FILESIZE = 8192;
|
||||||
|
// ISO8601 timestamp.
|
||||||
|
static constexpr char FILE_DATE_FORMAT[] = "%FT%H%M%SZ";
|
||||||
|
|
||||||
|
MessageQueueIF* tcQueue;
|
||||||
|
PacketFilter filter;
|
||||||
|
CdsShortTimeStamper timeReader;
|
||||||
|
bool baseDirUninitialized = true;
|
||||||
|
const char* baseDir;
|
||||||
|
std::string baseName;
|
||||||
|
uint8_t currentSameSecNumber = 0;
|
||||||
|
std::filesystem::path basePath;
|
||||||
|
uint32_t rolloverDiffSeconds = 0;
|
||||||
|
std::array<uint8_t, MAX_FILESIZE> fileBuf{};
|
||||||
|
timeval currentTv;
|
||||||
|
timeval activeFileTv{};
|
||||||
|
std::optional<std::filesystem::path> activeFile;
|
||||||
|
SdCardMountedIF& sdcMan;
|
||||||
|
StorageManagerIF& tmStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get the queue where commands shall be sent.
|
||||||
|
* @return Id of command queue.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
|
||||||
|
|
||||||
|
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
|
||||||
|
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
|
||||||
|
static ReturnValue_t pathToTm(const std::filesystem::path& path, struct tm& time);
|
||||||
|
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp, TmFunnelBase& funnel);
|
||||||
|
bool updateBaseDir();
|
||||||
|
ReturnValue_t assignAndOrCreateMostRecentFile();
|
||||||
|
ReturnValue_t storePacket(PusTmReader& reader);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_TMTC_TMSTOREBACKEND_H_ */
|
@ -1,22 +1,87 @@
|
|||||||
#include "PusTmFunnel.h"
|
#include "PusTmFunnel.h"
|
||||||
|
|
||||||
|
#include "eive/definitions.h"
|
||||||
|
#include "eive/objects.h"
|
||||||
|
#include "fsfw/ipc/CommandMessage.h"
|
||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
#include "fsfw/objectmanager.h"
|
#include "fsfw/objectmanager.h"
|
||||||
|
#include "fsfw/pus/Service5EventReporting.h"
|
||||||
|
#include "fsfw/tmstorage/TmStoreMessage.h"
|
||||||
#include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h"
|
#include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h"
|
||||||
|
#include "tmtc/pusIds.h"
|
||||||
|
|
||||||
PusTmFunnel::PusTmFunnel(object_id_t objectId, TimeReaderIF &timeReader, StorageManagerIF &tmStore,
|
PusTmFunnel::PusTmFunnel(TmFunnelBase::FunnelCfg cfg, TimeReaderIF &timeReader,
|
||||||
uint32_t messageDepth)
|
SdCardMountedIF &sdcMan)
|
||||||
: TmFunnelBase(objectId, tmStore, messageDepth), timeReader(timeReader) {}
|
: TmFunnelBase(cfg),
|
||||||
|
timeReader(timeReader),
|
||||||
|
miscStore(objects::MISC_TM_STORE, "tm", "misc", RolloverInterval::HOURLY, 2, tmStore, sdcMan),
|
||||||
|
okStore(objects::OK_TM_STORE, "tm", "ok", RolloverInterval::MINUTELY, 30, tmStore, sdcMan),
|
||||||
|
notOkStore(objects::NOT_OK_TM_STORE, "tm", "nok", RolloverInterval::MINUTELY, 30, tmStore,
|
||||||
|
sdcMan),
|
||||||
|
hkStore(objects::HK_TM_STORE, "tm", "hk", RolloverInterval::MINUTELY, 15, tmStore, sdcMan),
|
||||||
|
sdcMan(sdcMan) {
|
||||||
|
Clock::getClock_timeval(¤tTv);
|
||||||
|
Clock::getUptime(&lastTvUpdate);
|
||||||
|
hkStore.addApid(config::EIVE_PUS_APID);
|
||||||
|
hkStore.addService(pus::PUS_SERVICE_3);
|
||||||
|
miscStore.addApid(config::EIVE_PUS_APID);
|
||||||
|
miscStore.addService(pus::PUS_SERVICE_17);
|
||||||
|
miscStore.addService(pus::PUS_SERVICE_2);
|
||||||
|
miscStore.addService(pus::PUS_SERVICE_200);
|
||||||
|
miscStore.addService(pus::PUS_SERVICE_201);
|
||||||
|
miscStore.addService(pus::PUS_SERVICE_9);
|
||||||
|
miscStore.addService(pus::PUS_SERVICE_20);
|
||||||
|
okStore.addApid(config::EIVE_PUS_APID);
|
||||||
|
okStore.addServiceSubservice(pus::PUS_SERVICE_5,
|
||||||
|
Service5EventReporting::Subservice::NORMAL_REPORT);
|
||||||
|
okStore.addService(pus::PUS_SERVICE_8);
|
||||||
|
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 1);
|
||||||
|
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 3);
|
||||||
|
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 5);
|
||||||
|
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 7);
|
||||||
|
notOkStore.addApid(config::EIVE_PUS_APID);
|
||||||
|
notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 2);
|
||||||
|
notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 3);
|
||||||
|
notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 4);
|
||||||
|
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 2);
|
||||||
|
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 4);
|
||||||
|
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 6);
|
||||||
|
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 8);
|
||||||
|
}
|
||||||
|
|
||||||
PusTmFunnel::~PusTmFunnel() = default;
|
PusTmFunnel::~PusTmFunnel() = default;
|
||||||
|
|
||||||
ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
|
ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
|
||||||
|
CommandMessage cmdMessage;
|
||||||
|
ReturnValue_t result;
|
||||||
|
try {
|
||||||
|
result = okStore.handleCommandQueue(ipcStore, *this);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::error << "PusTmFunnel::performOperation: Issue handling OK store command" << std::endl;
|
||||||
|
}
|
||||||
|
result = notOkStore.handleCommandQueue(ipcStore, *this);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::error << "PusTmFunnel::performOperation: Issue handling NOT OK store command"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
result = hkStore.handleCommandQueue(ipcStore, *this);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::error << "PusTmFunnel::performOperation: Issue handling HK store command" << std::endl;
|
||||||
|
}
|
||||||
|
result = miscStore.handleCommandQueue(ipcStore, *this);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::error << "PusTmFunnel::performOperation: Issue handling MISC store command" << std::endl;
|
||||||
|
}
|
||||||
|
} catch (const std::bad_optional_access &e) {
|
||||||
|
sif::error << e.what() << "when handling TM store command" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
TmTcMessage currentMessage;
|
TmTcMessage currentMessage;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
ReturnValue_t status = tmQueue->receiveMessage(¤tMessage);
|
result = tmQueue->receiveMessage(¤tMessage);
|
||||||
while (status == returnvalue::OK) {
|
while (result == returnvalue::OK) {
|
||||||
status = handlePacket(currentMessage);
|
result = handleTmPacket(currentMessage);
|
||||||
if (status != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "TmFunnel packet handling failed" << std::endl;
|
sif::warning << "TmFunnel packet handling failed" << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -25,16 +90,16 @@ ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
|
|||||||
sif::error << "PusTmFunnel: Possible message storm detected" << std::endl;
|
sif::error << "PusTmFunnel: Possible message storm detected" << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
status = tmQueue->receiveMessage(¤tMessage);
|
result = tmQueue->receiveMessage(¤tMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == MessageQueueIF::EMPTY) {
|
if (result == MessageQueueIF::EMPTY) {
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
return status;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) {
|
ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) {
|
||||||
uint8_t *packetData = nullptr;
|
uint8_t *packetData = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
store_address_t origStoreId = message.getStorageId();
|
store_address_t origStoreId = message.getStorageId();
|
||||||
@ -54,36 +119,38 @@ ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) {
|
|||||||
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
|
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
|
||||||
packet.updateErrorControl();
|
packet.updateErrorControl();
|
||||||
|
|
||||||
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
|
timeval currentUptime{};
|
||||||
const auto &dest = destinations[idx];
|
Clock::getUptime(¤tUptime);
|
||||||
if (destinations.size() > 1) {
|
if (currentUptime.tv_sec - lastTvUpdate.tv_sec >
|
||||||
if (idx < destinations.size() - 1) {
|
static_cast<signed int>(TV_UPDATE_INTERVAL_SECS)) {
|
||||||
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
|
Clock::getClock_timeval(¤tTv);
|
||||||
// to bother with send order and where the data is deleted.
|
lastTvUpdate = currentUptime;
|
||||||
store_address_t storeId;
|
|
||||||
result = tmStore.addData(&storeId, packetData, size);
|
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
message.setStorageId(storeId);
|
|
||||||
} else {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PusTmFunnel::handlePacket: Store too full to create data copy"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
message.setStorageId(origStoreId);
|
bool sdcUsable = sdcMan.isSdCardUsable(std::nullopt);
|
||||||
|
initStoresIfPossible(sdcUsable);
|
||||||
|
if (sdcUsable) {
|
||||||
|
miscStore.passPacket(packet);
|
||||||
|
okStore.passPacket(packet);
|
||||||
|
notOkStore.passPacket(packet);
|
||||||
|
hkStore.passPacket(packet);
|
||||||
}
|
}
|
||||||
}
|
return sendPacketToDestinations(origStoreId, message, packetData, size);
|
||||||
result = tmQueue->sendMessage(dest.queueId, &message);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler " << dest.name
|
|
||||||
<< " failed" << std::endl;
|
|
||||||
#endif
|
|
||||||
tmStore.deleteData(message.getStorageId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *PusTmFunnel::getName() const { return "PUS TM Funnel"; }
|
const char *PusTmFunnel::getName() const { return "PUS TM Funnel"; }
|
||||||
|
|
||||||
|
void PusTmFunnel::initStoresIfPossible(bool sdCardUsable) {
|
||||||
|
if (not storesInitialized and sdCardUsable and sdcMan.getCurrentMountPrefix() != nullptr) {
|
||||||
|
miscStore.initializeTmStore();
|
||||||
|
okStore.initializeTmStore();
|
||||||
|
hkStore.initializeTmStore();
|
||||||
|
notOkStore.initializeTmStore();
|
||||||
|
storesInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PusTmFunnel::initialize() {
|
||||||
|
initStoresIfPossible(sdcMan.isSdCardUsable(std::nullopt));
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
@ -10,33 +10,43 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "PersistentTmStore.h"
|
||||||
|
#include "fsfw/ipc/CommandMessage.h"
|
||||||
#include "fsfw/timemanager/TimeReaderIF.h"
|
#include "fsfw/timemanager/TimeReaderIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief TM Recipient.
|
* @brief TM Recipient.
|
||||||
* @details
|
* @details
|
||||||
* TODO: Add support for TM storage by using the (or a) LIVE flag provided by the CCSDS or Syrlinks
|
* Main telemetry receiver. All generated telemetry is funneled into this object.
|
||||||
* handler. If we are in LIVE TM mode, forward TM to downlink destination directly. Otherwise,
|
|
||||||
* forward to TM storage backend which stores TMs into files.
|
|
||||||
* Main telemetry receiver. All generated telemetry is funneled into
|
|
||||||
* this object.
|
|
||||||
* @ingroup utility
|
* @ingroup utility
|
||||||
* @author J. Meier, R. Mueller
|
* @author J. Meier, R. Mueller
|
||||||
*/
|
*/
|
||||||
class PusTmFunnel : public TmFunnelBase {
|
class PusTmFunnel : public TmFunnelBase {
|
||||||
public:
|
public:
|
||||||
explicit PusTmFunnel(object_id_t objectId, TimeReaderIF &timeReader, StorageManagerIF &tmStore,
|
PusTmFunnel(TmFunnelBase::FunnelCfg cfg, TimeReaderIF &timeReader, SdCardMountedIF &sdcMan);
|
||||||
uint32_t messageDepth = 10);
|
|
||||||
[[nodiscard]] const char *getName() const override;
|
[[nodiscard]] const char *getName() const override;
|
||||||
~PusTmFunnel() override;
|
~PusTmFunnel() override;
|
||||||
|
|
||||||
ReturnValue_t performOperation(uint8_t operationCode);
|
ReturnValue_t performOperation(uint8_t operationCode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Update TV stamp every 5 minutes
|
||||||
|
static constexpr dur_millis_t TV_UPDATE_INTERVAL_SECS = 60 * 5;
|
||||||
|
|
||||||
uint16_t sourceSequenceCount = 0;
|
uint16_t sourceSequenceCount = 0;
|
||||||
TimeReaderIF &timeReader;
|
TimeReaderIF &timeReader;
|
||||||
|
bool storesInitialized = false;
|
||||||
|
timeval currentTv{};
|
||||||
|
timeval lastTvUpdate{};
|
||||||
|
PersistentTmStore miscStore;
|
||||||
|
PersistentTmStore okStore;
|
||||||
|
PersistentTmStore notOkStore;
|
||||||
|
PersistentTmStore hkStore;
|
||||||
|
SdCardMountedIF &sdcMan;
|
||||||
|
|
||||||
ReturnValue_t handlePacket(TmTcMessage &message);
|
ReturnValue_t handleTmPacket(TmTcMessage &message);
|
||||||
|
void initStoresIfPossible(bool sdCardUsable);
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H
|
#endif // FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H
|
||||||
|
85
mission/tmtc/Service15TmStorage.cpp
Normal file
85
mission/tmtc/Service15TmStorage.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include "Service15TmStorage.h"
|
||||||
|
|
||||||
|
#include <fsfw/objectmanager/ObjectManager.h>
|
||||||
|
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
||||||
|
|
||||||
|
#include "eive/objects.h"
|
||||||
|
#include "fsfw/tmstorage/TmStoreMessage.h"
|
||||||
|
|
||||||
|
using namespace returnvalue;
|
||||||
|
|
||||||
|
Service15TmStorage::Service15TmStorage(object_id_t objectId, uint16_t apid,
|
||||||
|
uint8_t numParallelCommands, uint16_t commandTimeoutSecs,
|
||||||
|
size_t queueDepth)
|
||||||
|
: CommandingServiceBase(objectId, apid, "PUS Service 15", 15, numParallelCommands,
|
||||||
|
commandTimeoutSecs, queueDepth) {}
|
||||||
|
|
||||||
|
ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) {
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservices::DELETE_UP_TO):
|
||||||
|
case (Subservices::START_BY_TIME_RANGE_RETRIEVAL): {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service15TmStorage::getMessageQueueAndObject(uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen,
|
||||||
|
MessageQueueId_t *id,
|
||||||
|
object_id_t *objectId) {
|
||||||
|
if (tcDataLen < 4) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::NETWORK);
|
||||||
|
auto *frontendIF = ObjectManager::instance()->get<TmStoreFrontendSimpleIF>(*objectId);
|
||||||
|
if (frontendIF == nullptr) {
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
*id = frontendIF->getCommandQueue();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen,
|
||||||
|
uint32_t *state, object_id_t objectId) {
|
||||||
|
if (subservice == Subservices::START_BY_TIME_RANGE_RETRIEVAL) {
|
||||||
|
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||||
|
// to time reading and reply handling
|
||||||
|
if (tcDataLen != 12) {
|
||||||
|
return INVALID_TC;
|
||||||
|
}
|
||||||
|
store_address_t storeId;
|
||||||
|
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
||||||
|
if (result != OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// Store timestamps
|
||||||
|
TmStoreMessage::setDownlinkContentTimeMessage(message, storeId);
|
||||||
|
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||||
|
} else if (subservice == Subservices::DELETE_UP_TO) {
|
||||||
|
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||||
|
// to time reading and reply handling
|
||||||
|
if (tcDataLen != 8) {
|
||||||
|
return INVALID_TC;
|
||||||
|
}
|
||||||
|
store_address_t storeId;
|
||||||
|
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
||||||
|
if (result != OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// Store timestamps
|
||||||
|
TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
|
||||||
|
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service15TmStorage::handleReply(const CommandMessage *reply,
|
||||||
|
Command_t previousCommand, uint32_t *state,
|
||||||
|
CommandMessage *optionalNextCommand,
|
||||||
|
object_id_t objectId, bool *isStep) {
|
||||||
|
return OK;
|
||||||
|
}
|
24
mission/tmtc/Service15TmStorage.h
Normal file
24
mission/tmtc/Service15TmStorage.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef MISSION_TMTC_SERVICE15TMSTORAGE_H_
|
||||||
|
#define MISSION_TMTC_SERVICE15TMSTORAGE_H_
|
||||||
|
|
||||||
|
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||||
|
|
||||||
|
class Service15TmStorage : public CommandingServiceBase {
|
||||||
|
public:
|
||||||
|
enum Subservices : uint8_t { START_BY_TIME_RANGE_RETRIEVAL = 9, DELETE_UP_TO = 11 };
|
||||||
|
explicit Service15TmStorage(object_id_t objectId, uint16_t apid, uint8_t numParallelCommands,
|
||||||
|
uint16_t commandTimeoutSecs = 60, size_t queueDepth = 10);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReturnValue_t isValidSubservice(uint8_t subservice) override;
|
||||||
|
ReturnValue_t getMessageQueueAndObject(uint8_t subservice, const uint8_t* tcData,
|
||||||
|
size_t tcDataLen, MessageQueueId_t* id,
|
||||||
|
object_id_t* objectId) override;
|
||||||
|
ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
|
||||||
|
size_t tcDataLen, uint32_t* state, object_id_t objectId) override;
|
||||||
|
ReturnValue_t handleReply(const CommandMessage* reply, Command_t previousCommand, uint32_t* state,
|
||||||
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
|
bool* isStep) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_TMTC_SERVICE15TMSTORAGE_H_ */
|
@ -1,10 +1,12 @@
|
|||||||
#include "TmFunnelBase.h"
|
#include "TmFunnelBase.h"
|
||||||
|
|
||||||
|
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||||
|
|
||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
|
|
||||||
TmFunnelBase::TmFunnelBase(object_id_t objectId, StorageManagerIF &tmStore, uint32_t tmMsgDepth)
|
TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
|
||||||
: SystemObject(objectId), tmStore(tmStore) {
|
: SystemObject(cfg.objectId), tmStore(cfg.tmStore), ipcStore(cfg.ipcStore) {
|
||||||
tmQueue = QueueFactory::instance()->createMessageQueue(tmMsgDepth);
|
tmQueue = QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
TmFunnelBase::~TmFunnelBase() { QueueFactory::instance()->deleteMessageQueue(tmQueue); }
|
TmFunnelBase::~TmFunnelBase() { QueueFactory::instance()->deleteMessageQueue(tmQueue); }
|
||||||
@ -18,3 +20,38 @@ void TmFunnelBase::addDestination(const char *name, const AcceptsTelemetryIF &do
|
|||||||
auto queueId = downlinkDestination.getReportReceptionQueue(vcid);
|
auto queueId = downlinkDestination.getReportReceptionQueue(vcid);
|
||||||
destinations.emplace_back(name, queueId, vcid);
|
destinations.emplace_back(name, queueId, vcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TmFunnelBase::sendPacketToDestinations(store_address_t origStoreId,
|
||||||
|
TmTcMessage &message,
|
||||||
|
const uint8_t *packetData, size_t size) {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
|
||||||
|
const auto &dest = destinations[idx];
|
||||||
|
if (destinations.size() > 1) {
|
||||||
|
if (idx < destinations.size() - 1) {
|
||||||
|
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
|
||||||
|
// to bother with send order and where the data is deleted.
|
||||||
|
store_address_t storeId;
|
||||||
|
result = tmStore.addData(&storeId, packetData, size);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
message.setStorageId(storeId);
|
||||||
|
} else {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PusTmFunnel::handlePacket: Store too full to create data copy"
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.setStorageId(origStoreId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = tmQueue->sendMessage(dest.queueId, &message);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl;
|
||||||
|
#endif
|
||||||
|
tmStore.deleteData(message.getStorageId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -3,21 +3,36 @@
|
|||||||
|
|
||||||
#include <fsfw/objectmanager/SystemObject.h>
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
#include <fsfw/storagemanager/StorageManagerIF.h>
|
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||||
|
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
||||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
|
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
TmFunnelBase(object_id_t objectId, StorageManagerIF& tmStore, uint32_t tmMsgDepth);
|
struct FunnelCfg {
|
||||||
|
FunnelCfg(object_id_t objId, StorageManagerIF& tmStore, StorageManagerIF& ipcStore,
|
||||||
|
uint32_t tmMsgDepth)
|
||||||
|
: objectId(objId), tmStore(tmStore), ipcStore(ipcStore), tmMsgDepth(tmMsgDepth) {}
|
||||||
|
object_id_t objectId;
|
||||||
|
StorageManagerIF& tmStore;
|
||||||
|
StorageManagerIF& ipcStore;
|
||||||
|
uint32_t tmMsgDepth;
|
||||||
|
};
|
||||||
|
explicit TmFunnelBase(FunnelCfg cfg);
|
||||||
void addDestination(const char* name, const AcceptsTelemetryIF& downlinkDestination,
|
void addDestination(const char* name, const AcceptsTelemetryIF& downlinkDestination,
|
||||||
uint8_t vcid = 0);
|
uint8_t vcid = 0);
|
||||||
|
ReturnValue_t sendPacketToDestinations(store_address_t origStoreId, TmTcMessage& message,
|
||||||
|
const uint8_t* packetData, size_t size);
|
||||||
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
||||||
|
|
||||||
virtual ~TmFunnelBase();
|
~TmFunnelBase() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageManagerIF& tmStore;
|
StorageManagerIF& tmStore;
|
||||||
|
StorageManagerIF& ipcStore;
|
||||||
|
|
||||||
struct Destination {
|
struct Destination {
|
||||||
Destination(const char* name, MessageQueueId_t queueId, uint8_t virtualChannel)
|
Destination(const char* name, MessageQueueId_t queueId, uint8_t virtualChannel)
|
||||||
: name(name), queueId(queueId), virtualChannel(virtualChannel) {}
|
: name(name), queueId(queueId), virtualChannel(virtualChannel) {}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
target_sources(
|
target_sources(
|
||||||
${LIB_EIVE_MISSION} PRIVATE Timestamp.cpp ProgressPrinter.cpp Filenaming.cpp
|
${LIB_EIVE_MISSION} PRIVATE Timestamp.cpp ProgressPrinter.cpp Filenaming.cpp
|
||||||
GlobalConfigHandler.cpp)
|
GlobalConfigHandler.cpp DummySdCardManager.cpp)
|
||||||
|
13
mission/utility/DummySdCardManager.cpp
Normal file
13
mission/utility/DummySdCardManager.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "DummySdCardManager.h"
|
||||||
|
|
||||||
|
DummySdCardManager::DummySdCardManager(std::string prefix) : prefix(std::move(prefix)) {}
|
||||||
|
|
||||||
|
const char* DummySdCardManager::getCurrentMountPrefix() const { return prefix.c_str(); }
|
||||||
|
|
||||||
|
bool DummySdCardManager::isSdCardUsable(std::optional<sd::SdCard> sdCard) { return true; }
|
||||||
|
|
||||||
|
std::optional<sd::SdCard> DummySdCardManager::getPreferredSdCard() const { return std::nullopt; }
|
||||||
|
|
||||||
|
void DummySdCardManager::setActiveSdCard(sd::SdCard sdCard) {}
|
||||||
|
|
||||||
|
std::optional<sd::SdCard> DummySdCardManager::getActiveSdCard() const { return std::nullopt; }
|
@ -2,11 +2,11 @@
|
|||||||
#define BSP_LINUX_BOARD_RPISDCARDMANAGER_H_
|
#define BSP_LINUX_BOARD_RPISDCARDMANAGER_H_
|
||||||
#include <mission/memory/SdCardMountedIF.h>
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
class RPiSdCardManager : public SdCardMountedIF {
|
class DummySdCardManager : public SdCardMountedIF {
|
||||||
public:
|
public:
|
||||||
RPiSdCardManager(std::string prefix);
|
DummySdCardManager(std::string prefix);
|
||||||
const std::string& getCurrentMountPrefix() const override;
|
const char* getCurrentMountPrefix() const override;
|
||||||
bool isSdCardUsable(sd::SdCard sdCard) override;
|
bool isSdCardUsable(std::optional<sd::SdCard> sdCard) override;
|
||||||
std::optional<sd::SdCard> getPreferredSdCard() const override;
|
std::optional<sd::SdCard> getPreferredSdCard() const override;
|
||||||
void setActiveSdCard(sd::SdCard sdCard) override;
|
void setActiveSdCard(sd::SdCard sdCard) override;
|
||||||
std::optional<sd::SdCard> getActiveSdCard() const override;
|
std::optional<sd::SdCard> getActiveSdCard() const override;
|
@ -4,8 +4,10 @@ OBSW Release Checklist
|
|||||||
# Pre-Release
|
# Pre-Release
|
||||||
|
|
||||||
1. Update version in `CMakeLists.txt`
|
1. Update version in `CMakeLists.txt`
|
||||||
2. Verify that the Q7S, Q7S EM and Host build are working
|
2. Re-run the auto-formatters with the `scripts/auto-formatter.sh` script
|
||||||
3. Wait for CI/CD results
|
3. Re-run the generators with `generators/gen.py all`
|
||||||
|
4. Verify that the Q7S, Q7S EM and Host build are working
|
||||||
|
5. Wait for CI/CD results
|
||||||
|
|
||||||
# Post-Release
|
# Post-Release
|
||||||
|
|
||||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit 24f0d8e1a6a8ea1323623932e699326214c78159
|
Subproject commit 9720fcddecb04b228dc5eb0d064f15a12ef8daca
|
@ -4,6 +4,7 @@ add_subdirectory(mocks)
|
|||||||
target_sources(${UNITTEST_NAME} PRIVATE
|
target_sources(${UNITTEST_NAME} PRIVATE
|
||||||
main.cpp
|
main.cpp
|
||||||
testEnvironment.cpp
|
testEnvironment.cpp
|
||||||
|
testStampInFilename.cpp
|
||||||
hdlcEncodingRw.cpp
|
hdlcEncodingRw.cpp
|
||||||
printChar.cpp
|
printChar.cpp
|
||||||
)
|
)
|
21
unittest/testStampInFilename.cpp
Normal file
21
unittest/testStampInFilename.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
|
||||||
|
TEST_CASE("Stamp in Filename", "[Stamp In Filename]") {
|
||||||
|
Clock::TimeOfDay_t tod;
|
||||||
|
std::string baseName = "verif";
|
||||||
|
std::string pathStr = "verif_2022-05-25T16:55:23Z.bin";
|
||||||
|
unsigned int underscorePos = pathStr.find_last_of('_');
|
||||||
|
std::string stampStr = pathStr.substr(underscorePos + 1);
|
||||||
|
float seconds = 0.0;
|
||||||
|
char* prefix = nullptr;
|
||||||
|
int count =
|
||||||
|
sscanf(stampStr.c_str(),
|
||||||
|
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32 "Z",
|
||||||
|
&tod.year, &tod.month, &tod.day, &tod.hour, &tod.minute, &tod.second);
|
||||||
|
static_cast<void>(count);
|
||||||
|
CHECK(count == 6);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user