Compare commits
42 Commits
mdemke/mgm
...
mohr/warni
Author | SHA1 | Date | |
---|---|---|---|
2ca9eb4204 | |||
45b686a028 | |||
329e80e7ee | |||
3772db4753 | |||
3d13ead275 | |||
e7e9ce4baf | |||
e4c11f8107 | |||
270622a5f1 | |||
4b52e5bec4 | |||
efc2773f84 | |||
87bb29a66a | |||
45963b2064 | |||
bc312243df | |||
9589d702dd | |||
c66fab90f9 | |||
3e8446ba8b | |||
e37af4fe70 | |||
941bf61f28 | |||
70fd9ff3e5 | |||
81c5b2ec95 | |||
7426e10f82 | |||
123c81777a | |||
dcc28622a5 | |||
6d85fa155e | |||
e6af6200ae | |||
5ca3e83934 | |||
6adabb059a | |||
5d0a5cd201 | |||
adb8483bb0 | |||
fdfdce2fb0 | |||
90efb132d0 | |||
fe9804d922 | |||
a0eae66c35 | |||
e131480d5f | |||
90bafbb6de | |||
47d85fb61c | |||
39dad5f45b | |||
a993c4e0d4 | |||
fe9cc20d00 | |||
552a12a6ad | |||
13639feec6 | |||
654de0f586 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,5 @@
|
|||||||
# PyCharm and CLion
|
# PyCharm and CLion
|
||||||
.idea/*
|
/.idea/*
|
||||||
!/.idea/runConfigurations
|
!/.idea/runConfigurations
|
||||||
!/.idea/cmake.xml
|
!/.idea/cmake.xml
|
||||||
!/.idea/codeStyles
|
!/.idea/codeStyles
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "automation/msvc-wine"]
|
||||||
|
path = automation/msvc-wine
|
||||||
|
url = https://github.com/mstorsjo/msvc-wine
|
||||||
|
8
.idea/cmake.xml
generated
8
.idea/cmake.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CMakeSharedSettings">
|
|
||||||
<configurations>
|
|
||||||
<configuration PROFILE_NAME="Debug Test" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON" NO_GENERATOR="true" />
|
|
||||||
</configurations>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
166
CHANGELOG.md
166
CHANGELOG.md
@ -8,86 +8,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
## Fixes
|
# [v6.0.0]
|
||||||
|
|
||||||
- FreshDeviceHandlerBase did not initialize the fdirInstance
|
|
||||||
- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source
|
|
||||||
data with a size limited only by the size of `size_t`.
|
|
||||||
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
|
|
||||||
number fields stored the actual length of the field instead of the length minus 1 like specified
|
|
||||||
in the CFDP standard.
|
|
||||||
- PUS Health Service: Size check for set health command.
|
|
||||||
Perform operation completion for announce health command.
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
|
|
||||||
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
|
|
||||||
- Small tweak for version getter
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
|
|
||||||
|
|
||||||
## Added
|
|
||||||
|
|
||||||
- add CFDP subsystem ID
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
|
|
||||||
- `PusTmZcWriter` now exposes API to set message counter field.
|
|
||||||
- Relative timeshift in the PUS time service.
|
|
||||||
|
|
||||||
## Changed
|
|
||||||
|
|
||||||
- The PUS time service now dumps the time before setting a new time and after having set the
|
|
||||||
time.
|
|
||||||
- HK generation is now countdown based.
|
|
||||||
- Bump ETL version to 20.35.14
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
|
|
||||||
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
|
|
||||||
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
|
|
||||||
- Assert that `FixedArrayList` is larger than 0 at compile time.
|
|
||||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
|
|
||||||
- Health functions are virtual now.
|
|
||||||
- PUS Service Base request queue depth and maximum number of handled packets per cycle is now
|
|
||||||
configurable.
|
|
||||||
|
|
||||||
## Added
|
|
||||||
|
|
||||||
- `EventManager`: Add function to print all listeners.
|
|
||||||
|
|
||||||
## Changed
|
|
||||||
|
|
||||||
- `EventManager`: Queue depth is configurable now
|
|
||||||
|
|
||||||
# [v6.0.0] 2023-02-10
|
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
- Mode Service: Add allowed subservice
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739
|
|
||||||
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
|
|
||||||
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
|
|
||||||
subservice not working properly.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736
|
|
||||||
- Memory leak fixes for the TCP/IP TMTC bridge.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
|
|
||||||
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
|
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
|
||||||
seconds instead of uptime.
|
seconds instead of uptime.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
|
||||||
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
|
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
|
||||||
only the X scaling factor was used.
|
only the X scaling factor was used.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
|
||||||
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733
|
|
||||||
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
|
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
|
||||||
to false correctly because the `read` and `write` calls were missing.
|
to false correctly because the `read` and `write` calls were missing.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728
|
|
||||||
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
|
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
|
||||||
of the correct unsegmented flags (0b11) as specified in the standard.
|
of the correct unsegmented flags (0b11) as specified in the standard.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727
|
|
||||||
- TC Scheduler Service 11: Add size and CRC check for contained TC.
|
- TC Scheduler Service 11: Add size and CRC check for contained TC.
|
||||||
Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720
|
|
||||||
- Only delete health table entry in `HealthHelper` destructor if
|
- Only delete health table entry in `HealthHelper` destructor if
|
||||||
health table was set.
|
health table was set.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
|
||||||
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
|
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
|
||||||
Also properly reset the reply size for successfull transfers and erroneous transfers.
|
Also properly reset the reply size for successfull transfers and erroneous transfers.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
|
||||||
@ -97,43 +35,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- `TcpTmTcServer.cpp`: The server was actually not able to handle
|
- `TcpTmTcServer.cpp`: The server was actually not able to handle
|
||||||
CCSDS packets which were clumped together. This has been fixed now.
|
CCSDS packets which were clumped together. This has been fixed now.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
|
||||||
- `CServiceHealthCommanding`: Add announce all health info implementation
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
|
|
||||||
- various fixes related to linux Unittests and memory leaks
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715
|
|
||||||
- small fix to allow teardown handling
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713
|
|
||||||
- fix compiler warning for fixed array list copy ctor
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704
|
|
||||||
- missing include
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703
|
|
||||||
- defaultconfig did not build anymore
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702
|
|
||||||
- hotfix
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699
|
|
||||||
- small fix for helper
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698
|
|
||||||
- missing retval conv
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697
|
|
||||||
- DHB Countdown Bug
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693
|
|
||||||
- doc corrections
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687
|
|
||||||
- better error printout
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686
|
|
||||||
- include correction
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683
|
|
||||||
- better warning for missing include paths
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676
|
|
||||||
- Service 11 regression
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670
|
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- `CServiceHealthCommanding`: Add announce all health info implementation
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
|
|
||||||
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
|
|
||||||
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
|
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
|
||||||
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
|
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
|
||||||
option on the TCP server. CTOR prototype has changed and expects an explicit
|
option on the TCP server. CTOR prototype has changed and expects an explicit
|
||||||
@ -145,36 +49,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
|
||||||
- Add new `UnsignedByteField` class
|
- Add new `UnsignedByteField` class
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
||||||
- publish documentation for development and master branch
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681
|
|
||||||
- Add Linux HAL options
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663
|
|
||||||
- Expand SerializeIF
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656
|
|
||||||
- PUS Service 11: Additional Safety Check
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666
|
|
||||||
- improvements for auto-formatter script
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665
|
|
||||||
- provide a weak print char impl
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674
|
|
||||||
|
|
||||||
## Removed
|
|
||||||
|
|
||||||
- now that doc server is up, remove markdown files
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688
|
|
||||||
- remove bsp specific code
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679
|
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
|
|
||||||
service ID customizable now. `CServiceHealthCommanding` expects configuration struct
|
|
||||||
`HealthServiceCfg` now
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
|
|
||||||
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
|
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
|
||||||
- Moved some container returnvalues to dedicated header and namespace
|
- Moved some container returnvalues to dedicated header and namespace
|
||||||
so they can be used without template specification.
|
to they can be used without template specification.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
|
||||||
- Remove default secondary header argument for
|
- Remove default secondary header argument for
|
||||||
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
||||||
@ -204,41 +85,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
||||||
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
||||||
|
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
||||||
|
interface itself so it can be re-used more easily. Also add new
|
||||||
|
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
||||||
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
|
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
|
||||||
- Make functions `const` where it makes sense
|
- Make functions `const` where it makes sense
|
||||||
- Add `const char* getName const` abstract function
|
- Add `const char* getName const` abstract function
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
|
||||||
- Generic TMTC Bridge Update
|
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
|
interface itself so it can be re-used more easily. Also add new
|
||||||
- comment tweak to event parser can read everything
|
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
||||||
- CMakeLists file updates
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731
|
|
||||||
- improve srv20 error messages
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723
|
|
||||||
- I2C Linux: remove duplicate printout
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718
|
|
||||||
- printout handling improvements
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717
|
|
||||||
- vec getter, reset for content
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716
|
|
||||||
- updates for source sequence counter
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714
|
|
||||||
- SP reader getPacketData is const now
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708
|
|
||||||
- refactoring of serial drivers for linux
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705
|
|
||||||
- Local Pool Update Remove Add Data Ignore Fault Argument
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701
|
|
||||||
- Switch to new documentation server
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694
|
|
||||||
- Windows Tweaks
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691
|
|
||||||
- Refactor Local Pool API
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667
|
|
||||||
- group MGM data in local pool vectors
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664
|
|
||||||
|
|
||||||
|
|
||||||
## CFDP
|
## CFDP
|
||||||
|
|
||||||
@ -258,7 +116,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
implementation without an extra component
|
implementation without an extra component
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
||||||
|
|
||||||
# [v5.0.0] 2022-07-25
|
# [v5.0.0] 25.07.2022
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
|
|||||||
# Version file handling #
|
# Version file handling #
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
|
|
||||||
set(FSFW_VERSION_IF_GIT_FAILS 6)
|
set(FSFW_VERSION_IF_GIT_FAILS 5)
|
||||||
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
||||||
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
||||||
|
|
||||||
@ -64,6 +64,13 @@ elseif(${CMAKE_CXX_STANDARD} LESS 17)
|
|||||||
"${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support")
|
"${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
# Manually tweak MSVC to emit (about) the same warnings as clang and gcc on linux
|
||||||
|
# needs to be done here using add_compile_definitions() (as opposed to target_compile_definitions()) to be available for all binaries and libraries
|
||||||
|
add_compile_options("/permissive-" /wd4267 /wd4244 /wd4244 /wd4305 /wd4805 /wd4267 /wd4646 /wd4065 /wd4996 /Dand=&& /Dor=|| /Dnot=!)
|
||||||
|
add_compile_definitions(NOMINMAX)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
|
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
|
||||||
|
|
||||||
set(FSFW_ETL_LIB_NAME etl)
|
set(FSFW_ETL_LIB_NAME etl)
|
||||||
@ -72,7 +79,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
|
|||||||
20
|
20
|
||||||
CACHE STRING "ETL library major version requirement")
|
CACHE STRING "ETL library major version requirement")
|
||||||
set(FSFW_ETL_LIB_VERSION
|
set(FSFW_ETL_LIB_VERSION
|
||||||
${FSFW_ETL_LIB_MAJOR_VERSION}.36.0
|
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
|
||||||
CACHE STRING "ETL library exact version requirement")
|
CACHE STRING "ETL library exact version requirement")
|
||||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||||
|
|
||||||
@ -80,7 +87,7 @@ set(FSFW_CATCH2_LIB_MAJOR_VERSION
|
|||||||
3
|
3
|
||||||
CACHE STRING "Catch2 library major version requirement")
|
CACHE STRING "Catch2 library major version requirement")
|
||||||
set(FSFW_CATCH2_LIB_VERSION
|
set(FSFW_CATCH2_LIB_VERSION
|
||||||
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.3.2
|
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
|
||||||
CACHE STRING "Catch2 library exact version requirement")
|
CACHE STRING "Catch2 library exact version requirement")
|
||||||
|
|
||||||
# Keep this off by default for now. See PR:
|
# Keep this off by default for now. See PR:
|
||||||
@ -158,7 +165,7 @@ if(FSFW_BUILD_TESTS)
|
|||||||
if(NOT Catch2_FOUND)
|
if(NOT Catch2_FOUND)
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent."
|
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
|
||||||
)
|
)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
@ -174,6 +181,27 @@ if(FSFW_BUILD_TESTS)
|
|||||||
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
||||||
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
||||||
|
|
||||||
|
if(FSFW_OSAL MATCHES "freertos")
|
||||||
|
message(STATUS "${MSG_PREFIX} Downloading FreeRTOS with FetchContent")
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
set(FreeRTOS_PORT posix)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
FreeRTOS
|
||||||
|
GIT_REPOSITORY https://egit.irs.uni-stuttgart.de/fsfw/FreeRTOS-LTS
|
||||||
|
GIT_TAG develop
|
||||||
|
GIT_SUBMODULES FreeRTOS/FreeRTOS-Kernel)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(FreeRTOS)
|
||||||
|
|
||||||
|
set(LIB_OS_NAME FreeRTOS)
|
||||||
|
target_include_directories(FreeRTOS PUBLIC unittests/testcfg/freertos)
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(FreeRTOS PRIVATE ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
|
||||||
project(${FSFW_TEST_TGT} CXX C)
|
project(${FSFW_TEST_TGT} CXX C)
|
||||||
add_executable(${FSFW_TEST_TGT})
|
add_executable(${FSFW_TEST_TGT})
|
||||||
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
@ -201,8 +229,8 @@ find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
|||||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
|
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
|
||||||
)
|
"etl with FindPackage")
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
@ -226,6 +254,7 @@ if(FSFW_FETCH_CONTENT_TARGETS)
|
|||||||
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_CORE_INC_PATH "inc")
|
set(FSFW_CORE_INC_PATH "inc")
|
||||||
@ -360,6 +389,9 @@ if(FSFW_BUILD_TESTS)
|
|||||||
endif()
|
endif()
|
||||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
|
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
|
||||||
${LIB_FSFW_NAME})
|
${LIB_FSFW_NAME})
|
||||||
|
if(FSFW_OSAL MATCHES "freertos")
|
||||||
|
target_link_libraries(${FSFW_TEST_TGT} PRIVATE FreeRTOS)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
|
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
|
||||||
@ -447,8 +479,47 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(COMPILER_FLAGS "/permissive-")
|
set(FSFW_WARNING_FLAGS
|
||||||
|
-Weverything
|
||||||
|
|
||||||
|
-Wno-gnu-anonymous-struct
|
||||||
|
-Wno-c++98-compat
|
||||||
|
-Wno-c++98-compat-pedantic
|
||||||
|
-Wno-covered-switch-default
|
||||||
|
-Wno-padded
|
||||||
|
-Wno-documentation
|
||||||
|
-Wno-weak-vtables
|
||||||
|
-Wno-c++98-c++11-compat-binary-literal
|
||||||
|
-Wno-documentation-unknown-command
|
||||||
|
-Wno-reserved-macro-identifier
|
||||||
|
-Wno-global-constructors
|
||||||
|
-Wno-reserved-identifier
|
||||||
|
-Wno-switch-enum
|
||||||
|
|
||||||
|
-Werror
|
||||||
|
#WTH?
|
||||||
|
-Wno-ctad-maybe-unsupported
|
||||||
|
#WIP
|
||||||
|
-Wno-undefined-func-template
|
||||||
|
-Wno-suggest-destructor-override
|
||||||
|
-Wno-suggest-override
|
||||||
|
-Wno-inconsistent-missing-destructor-override
|
||||||
|
-Wno-extra-semi
|
||||||
|
#could be useful:
|
||||||
|
-Wno-sign-conversion
|
||||||
|
-Wno-implicit-int-conversion
|
||||||
|
-Wno-shorten-64-to-32
|
||||||
|
-Wno-double-promotion
|
||||||
|
-Wno-float-conversion
|
||||||
|
-Wno-implicit-int-float-conversion
|
||||||
|
-Wno-implicit-float-conversion
|
||||||
|
-Wno-shadow-field-in-constructor
|
||||||
|
-Wno-shadow-field
|
||||||
|
-Wno-shadow
|
||||||
|
-Wno-unused-parameter
|
||||||
|
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Required include paths to compile the FSFW
|
# Required include paths to compile the FSFW
|
||||||
|
@ -5,7 +5,7 @@ RUN apt-get --yes upgrade
|
|||||||
|
|
||||||
#tzdata is a dependency, won't install otherwise
|
#tzdata is a dependency, won't install otherwise
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz rsync
|
RUN apt-get --yes install ca-certificates clang cmake doxygen g++ gcc git graphviz iputils-ping lcov make msitools nano ninja-build pip python3 python3-simplejson python3-six qemu-system-arm rsync valgrind wget winbind
|
||||||
|
|
||||||
RUN python3 -m pip install sphinx breathe
|
RUN python3 -m pip install sphinx breathe
|
||||||
|
|
||||||
@ -21,9 +21,37 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
|
|||||||
cmake -B build . && \
|
cmake -B build . && \
|
||||||
cmake --install build/
|
cmake --install build/
|
||||||
|
|
||||||
|
|
||||||
|
# install our own rtems build
|
||||||
|
RUN wget -qO- https://buggy.irs.uni-stuttgart.de/rtems_releases/rtems6-12.2.1.tar.bz2 | tar -xj -C /opt/
|
||||||
|
ENV PATH="$PATH:/opt/rtems/6/bin"
|
||||||
|
|
||||||
|
# install modern wine for MSVC, removing a conflicting file
|
||||||
|
RUN dpkg --add-architecture i386 && \
|
||||||
|
mkdir -pm755 /etc/apt/keyrings && \
|
||||||
|
wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key && \
|
||||||
|
wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/focal/winehq-focal.sources && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get --yes install winehq-stable
|
||||||
|
# silence wine
|
||||||
|
ENV WINEDEBUG=-all
|
||||||
|
|
||||||
|
|
||||||
|
# install MSVC using https://github.com/mstorsjo/msvc-wine
|
||||||
|
# see msvc-wine/LICENSE.txt
|
||||||
|
COPY msvc-wine/lowercase msvc-wine/fixinclude msvc-wine/install.sh msvc-wine/vsdownload.py ./
|
||||||
|
COPY msvc-wine/wrappers/* ./wrappers/
|
||||||
|
RUN PYTHONUNBUFFERED=1 ./vsdownload.py --accept-license --dest /opt/msvc && \
|
||||||
|
./install.sh /opt/msvc && \
|
||||||
|
rm lowercase fixinclude install.sh vsdownload.py && \
|
||||||
|
rm -rf wrappers
|
||||||
|
RUN wine64 wineboot --init && \
|
||||||
|
while pgrep wineserver > /dev/null; do sleep 1; done
|
||||||
|
|
||||||
|
|
||||||
#ssh needs a valid user to work
|
#ssh needs a valid user to work
|
||||||
RUN adduser --uid 114 jenkins
|
RUN addgroup -q --gid 117 jenkins && adduser -q --uid 114 --gid 117 jenkins
|
||||||
|
|
||||||
#add documentation server to known hosts
|
#add documentation server to known hosts
|
||||||
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
|
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
|
||||||
RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
|
RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
|
||||||
|
118
automation/Jenkinsfile
vendored
118
automation/Jenkinsfile
vendored
@ -2,86 +2,72 @@ pipeline {
|
|||||||
environment {
|
environment {
|
||||||
BUILDDIR_HOST = 'cmake-build-tests-host'
|
BUILDDIR_HOST = 'cmake-build-tests-host'
|
||||||
BUILDDIR_LINUX = 'cmake-build-tests-linux'
|
BUILDDIR_LINUX = 'cmake-build-tests-linux'
|
||||||
|
BUILDDIR_FREERTOS = 'cmake-build-tests-freertos'
|
||||||
|
BUILDDIR_RTEMS = 'cmake-build-tests-rtems'
|
||||||
|
BUILDDIR_WIN = 'cmake-build-tests-windows'
|
||||||
DOCDDIR = 'cmake-build-documentation'
|
DOCDDIR = 'cmake-build-documentation'
|
||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker {
|
||||||
image 'fsfw-ci:d6'
|
image 'fsfw-ci:d9'
|
||||||
args '--network host --sysctl fs.mqueue.msg_max=100'
|
args '--network host --sysctl fs.mqueue.msg_max=100'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Host') {
|
stage('Host-clang') {
|
||||||
stages{
|
steps {
|
||||||
stage('Clean') {
|
sh 'rm -rf $BUILDDIR_HOST'
|
||||||
steps {
|
|
||||||
sh 'rm -rf $BUILDDIR_HOST'
|
dir(BUILDDIR_HOST) {
|
||||||
}
|
sh 'CC=clang CXX=clang++ cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||||
}
|
sh 'cmake --build . -j4'
|
||||||
stage('Configure') {
|
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||||
steps {
|
|
||||||
dir(BUILDDIR_HOST) {
|
|
||||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
dir(BUILDDIR_HOST) {
|
|
||||||
sh 'cmake --build . -j4'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Unittests') {
|
|
||||||
steps {
|
|
||||||
dir(BUILDDIR_HOST) {
|
|
||||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Valgrind') {
|
|
||||||
steps {
|
|
||||||
dir(BUILDDIR_HOST) {
|
|
||||||
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Linux') {
|
stage('Linux-gcc') {
|
||||||
stages{
|
steps {
|
||||||
stage('Clean') {
|
sh 'rm -rf $BUILDDIR_LINUX'
|
||||||
steps {
|
|
||||||
sh 'rm -rf $BUILDDIR_LINUX'
|
dir(BUILDDIR_LINUX) {
|
||||||
}
|
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||||
|
sh 'cmake --build . -j4'
|
||||||
|
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||||
|
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||||
}
|
}
|
||||||
stage('Configure') {
|
}
|
||||||
steps {
|
}
|
||||||
dir(BUILDDIR_LINUX) {
|
stage('FreeRTOS-gcc') {
|
||||||
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
steps {
|
||||||
}
|
sh 'rm -rf $BUILDDIR_FREERTOS'
|
||||||
}
|
|
||||||
|
dir(BUILDDIR_FREERTOS) {
|
||||||
|
sh 'cmake -DFSFW_OSAL=freertos -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||||
|
sh 'cmake --build . -j4'
|
||||||
|
sh './fsfw-tests'
|
||||||
|
//sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||||
}
|
}
|
||||||
stage('Build') {
|
}
|
||||||
steps {
|
}
|
||||||
dir(BUILDDIR_LINUX) {
|
stage('rtems-gcc') {
|
||||||
sh 'cmake --build . -j4'
|
steps {
|
||||||
}
|
sh 'rm -rf $BUILDDIR_RTEMS'
|
||||||
}
|
|
||||||
|
dir(BUILDDIR_RTEMS) {
|
||||||
|
sh 'cmake -DFSFW_OSAL=rtems -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=../unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake ..'
|
||||||
|
sh 'cmake --build . -j4'
|
||||||
|
sh 'qemu-system-aarch64 -no-reboot -nographic -serial mon:stdio -semihosting -machine virt,gic-version=3 -cpu cortex-a72 -m 4000 -kernel fsfw-tests'
|
||||||
}
|
}
|
||||||
stage('Unittests') {
|
}
|
||||||
steps {
|
}
|
||||||
dir(BUILDDIR_LINUX) {
|
stage('Host-msvc') {
|
||||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
steps {
|
||||||
}
|
sh 'rm -rf $BUILDDIR_WIN'
|
||||||
}
|
|
||||||
}
|
dir(BUILDDIR_WIN) {
|
||||||
stage('Valgrind') {
|
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../unittests/testcfg/windows/cmake/x64-windows-toolchain.cmake -GNinja ..'
|
||||||
steps {
|
sh 'cmake --build . -j4'
|
||||||
dir(BUILDDIR_LINUX) {
|
sh 'wine64 fsfw-tests.exe'
|
||||||
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
automation/msvc-wine
Submodule
1
automation/msvc-wine
Submodule
Submodule automation/msvc-wine added at 2d2d7db0b5
@ -51,10 +51,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|||||||
html_theme = "alabaster"
|
html_theme = "alabaster"
|
||||||
|
|
||||||
html_theme_options = {
|
html_theme_options = {
|
||||||
"extra_nav_links": {
|
"extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
|
||||||
"Impressum": "https://www.uni-stuttgart.de/impressum",
|
|
||||||
"Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
#! /bin/python
|
|
||||||
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import urllib.request
|
|
||||||
import re
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="List undocumented PRs"
|
|
||||||
)
|
|
||||||
parser.add_argument("-v", "--version", type=str, required=True)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
match = re.search("([0-9]+\.[0-9]+\.[0-9]+)", args.version)
|
|
||||||
|
|
||||||
if not match:
|
|
||||||
print("invalid version")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
version = "v" + match.group(1)
|
|
||||||
|
|
||||||
print("looking for milestone for " + version + " ...")
|
|
||||||
|
|
||||||
|
|
||||||
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/milestones?name=" + version) as milestone_json:
|
|
||||||
milestones = json.load(milestone_json)
|
|
||||||
if (len(milestones) == 0):
|
|
||||||
print("did not find any milestone")
|
|
||||||
exit(1)
|
|
||||||
if (len(milestones) > 1):
|
|
||||||
print("found multiple milestons")
|
|
||||||
milestone_title = milestones[0]['title']
|
|
||||||
milestone = str(milestones[0]['id'])
|
|
||||||
print("Using Milestone \""+ milestone_title + "\" with id " + milestone)
|
|
||||||
|
|
||||||
milestone_prs = []
|
|
||||||
|
|
||||||
page = 1
|
|
||||||
last_count = 1;
|
|
||||||
while last_count != 0:
|
|
||||||
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/pulls?state=closed&milestone=" + str(milestone) + "&limit=100&page=" + str(page)) as pull_requests_json:
|
|
||||||
pull_requests = json.load(pull_requests_json)
|
|
||||||
for pr in pull_requests:
|
|
||||||
milestone_prs.append({'number': str(pr['number']), 'title' : pr['title']})
|
|
||||||
page += 1
|
|
||||||
last_count = len(pull_requests)
|
|
||||||
|
|
||||||
print("Found " + str(len(milestone_prs)) + " closed PRs in Milestone")
|
|
||||||
|
|
||||||
print("looking for CHANGELOG.md ...")
|
|
||||||
|
|
||||||
path = Path(".")
|
|
||||||
|
|
||||||
files = list(path.glob("CHANGELOG.md"))
|
|
||||||
|
|
||||||
if (len(files) != 1):
|
|
||||||
files = list(path.glob("../CHANGELOG.md"))
|
|
||||||
|
|
||||||
if (len(files) != 1):
|
|
||||||
print("did not find CHANGELOG.md. Run script in either root directory or scripts subfolder.")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
print("Scanning CHANGELOG.md ...")
|
|
||||||
|
|
||||||
changelog_prs = []
|
|
||||||
|
|
||||||
with open(files[0]) as changelog:
|
|
||||||
line = changelog.readline()
|
|
||||||
while (line):
|
|
||||||
#print("line: " + line)
|
|
||||||
match = re.search("\#.+(v[0-9]+\.[0-9]+\.[0-9]+)", line)
|
|
||||||
if (match):
|
|
||||||
if match.group(1) == version:
|
|
||||||
#print("found version")
|
|
||||||
line = changelog.readline()
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
#print("done with " + match.group(1))
|
|
||||||
break
|
|
||||||
|
|
||||||
match = re.search("PR: https://egit\.irs\.uni-stuttgart\.de/fsfw/fsfw/pulls/([0-9]+)", line)
|
|
||||||
if match:
|
|
||||||
changelog_prs.append(match.group(1))
|
|
||||||
|
|
||||||
line = changelog.readline()
|
|
||||||
|
|
||||||
print("Found " + str(len(changelog_prs)) + " PRs in CHANGELOG.md")
|
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
copy_array = changelog_prs.copy()
|
|
||||||
print("PRs in CHANGELOG.md that are not in Milestone:")
|
|
||||||
for pr in milestone_prs:
|
|
||||||
if pr['number'] in copy_array:
|
|
||||||
copy_array.remove(pr['number'])
|
|
||||||
for pr in copy_array:
|
|
||||||
print("https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr)
|
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
print("PRs in milestone that are not in CHANGELOG.md:")
|
|
||||||
|
|
||||||
for pr in milestone_prs:
|
|
||||||
if pr['number'] not in changelog_prs:
|
|
||||||
print("- " + pr['title'] + "\n PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr['number'])
|
|
||||||
|
|
||||||
main()
|
|
@ -32,7 +32,6 @@ add_subdirectory(timemanager)
|
|||||||
add_subdirectory(tmtcpacket)
|
add_subdirectory(tmtcpacket)
|
||||||
add_subdirectory(tmtcservices)
|
add_subdirectory(tmtcservices)
|
||||||
add_subdirectory(filesystem)
|
add_subdirectory(filesystem)
|
||||||
add_subdirectory(util)
|
|
||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
|
|
||||||
|
@ -59,24 +59,17 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
|
|||||||
|
|
||||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||||
store_address_t dataAddress) {
|
store_address_t dataAddress) {
|
||||||
bool hasAdditionalData = false;
|
|
||||||
const uint8_t* dataPtr = nullptr;
|
const uint8_t* dataPtr = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result;
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
if (dataAddress != store_address_t::invalid()) {
|
if (result != returnvalue::OK) {
|
||||||
hasAdditionalData = true;
|
CommandMessage reply;
|
||||||
result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
if (result != returnvalue::OK) {
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
CommandMessage reply;
|
return;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
if (hasAdditionalData) {
|
ipcStore->deleteData(dataAddress);
|
||||||
ipcStore->deleteData(dataAddress);
|
|
||||||
}
|
|
||||||
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
||||||
|
@ -16,8 +16,8 @@ class CommandActionHelper {
|
|||||||
public:
|
public:
|
||||||
explicit CommandActionHelper(CommandsActionsIF* owner);
|
explicit CommandActionHelper(CommandsActionsIF* owner);
|
||||||
virtual ~CommandActionHelper();
|
virtual ~CommandActionHelper();
|
||||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
|
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
|
||||||
const uint8_t* data = nullptr, uint32_t size = 0);
|
uint32_t size);
|
||||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
ReturnValue_t handleReply(CommandMessage* reply);
|
ReturnValue_t handleReply(CommandMessage* reply);
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
#define FSFW_CFDP_H
|
#define FSFW_CFDP_H
|
||||||
|
|
||||||
#include "cfdp/definitions.h"
|
#include "cfdp/definitions.h"
|
||||||
#include "cfdp/handler/DestHandler.h"
|
|
||||||
#include "cfdp/handler/FaultHandlerBase.h"
|
#include "cfdp/handler/FaultHandlerBase.h"
|
||||||
#include "cfdp/helpers.h"
|
|
||||||
#include "cfdp/tlv/Lv.h"
|
#include "cfdp/tlv/Lv.h"
|
||||||
#include "cfdp/tlv/StringLv.h"
|
#include "cfdp/tlv/StringLv.h"
|
||||||
#include "cfdp/tlv/Tlv.h"
|
#include "cfdp/tlv/Tlv.h"
|
||||||
|
@ -4,9 +4,8 @@ CfdpMessage::CfdpMessage() = default;
|
|||||||
|
|
||||||
CfdpMessage::~CfdpMessage() = default;
|
CfdpMessage::~CfdpMessage() = default;
|
||||||
|
|
||||||
void CfdpMessage::setPutRequest(CommandMessage *message, store_address_t putRequest) {
|
void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
|
||||||
message->setCommand(PUT_REQUEST);
|
message->setParameter(cfdpPacket.raw);
|
||||||
message->setParameter(putRequest.raw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {
|
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {
|
||||||
|
@ -11,11 +11,9 @@ class CfdpMessage {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
|
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
|
||||||
static const Command_t PUT_REQUEST = MAKE_COMMAND_ID(1);
|
|
||||||
static const Command_t CANCEL_REQUEST = MAKE_COMMAND_ID(1);
|
|
||||||
|
|
||||||
virtual ~CfdpMessage();
|
virtual ~CfdpMessage();
|
||||||
static void setPutRequest(CommandMessage* message, store_address_t putRequest);
|
static void setCommand(CommandMessage* message, store_address_t cfdpPacket);
|
||||||
|
|
||||||
static store_address_t getStoreId(const CommandMessage* message);
|
static store_address_t getStoreId(const CommandMessage* message);
|
||||||
|
|
||||||
|
@ -8,14 +8,11 @@
|
|||||||
|
|
||||||
namespace cfdp {
|
namespace cfdp {
|
||||||
|
|
||||||
/**
|
struct FileSize : public SerializeIF {
|
||||||
* Helper type for the CFDP File Size Sensitive (FSS) fields.
|
|
||||||
*/
|
|
||||||
struct Fss : public SerializeIF {
|
|
||||||
public:
|
public:
|
||||||
Fss() = default;
|
FileSize() = default;
|
||||||
|
|
||||||
explicit Fss(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
|
explicit FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
|
||||||
|
|
||||||
[[nodiscard]] uint64_t value() const { return fileSize; }
|
[[nodiscard]] uint64_t value() const { return fileSize; }
|
||||||
|
|
||||||
@ -24,7 +21,7 @@ struct Fss : public SerializeIF {
|
|||||||
this->largeFile = isLarge;
|
this->largeFile = isLarge;
|
||||||
return serialize(buffer, size, maxSize, streamEndianness);
|
return serialize(buffer, size, maxSize, streamEndianness);
|
||||||
}
|
}
|
||||||
|
using SerializeIF::serialize;
|
||||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override {
|
Endianness streamEndianness) const override {
|
||||||
if (not largeFile) {
|
if (not largeFile) {
|
@ -4,7 +4,7 @@
|
|||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
|
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
|
||||||
ReturnValue_t result = this->setValueAndWidth(width, value);
|
ReturnValue_t result = this->setValue(width, value);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
#if FSFW_DISABLE_PRINTOUT == 0
|
#if FSFW_DISABLE_PRINTOUT == 0
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -20,8 +20,8 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o
|
|||||||
|
|
||||||
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
|
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
|
||||||
|
|
||||||
ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uint64_t value_) {
|
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, uint64_t value_) {
|
||||||
switch (width_) {
|
switch (widthInBytes) {
|
||||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||||
if (value_ > UINT8_MAX) {
|
if (value_ > UINT8_MAX) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
@ -43,14 +43,11 @@ ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uin
|
|||||||
this->value.fourBytes = value_;
|
this->value.fourBytes = value_;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
|
||||||
this->value.eightBytes = value_;
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->width = width_;
|
this->width = widthInBytes;
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,9 +62,6 @@ uint64_t cfdp::VarLenField::getValue() const {
|
|||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
return value.fourBytes;
|
return value.fourBytes;
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
|
||||||
return value.eightBytes;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -90,10 +84,6 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_
|
|||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
|
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
|
||||||
return SerializeAdapter::serialize(&value.eightBytes, buffer, size, maxSize,
|
|
||||||
streamEndianness);
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
@ -108,16 +98,11 @@ ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const ui
|
|||||||
return deSerialize(buffer, size, streamEndianness);
|
return deSerialize(buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t cfdp::VarLenField::setValue(uint64_t value_) {
|
|
||||||
return setValueAndWidth(getWidth(), value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
|
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
Endianness streamEndianness) {
|
Endianness streamEndianness) {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||||
value.oneByte = **buffer;
|
value.oneByte = **buffer;
|
||||||
*buffer += 1;
|
|
||||||
*size += 1;
|
*size += 1;
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
@ -127,9 +112,6 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz
|
|||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
|
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
|
||||||
return SerializeAdapter::deSerialize(&value.eightBytes, buffer, size, streamEndianness);
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
@ -153,5 +135,3 @@ bool cfdp::VarLenField::operator==(const cfdp::VarLenField &other) const {
|
|||||||
bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const {
|
bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const {
|
||||||
return not(*this == other);
|
return not(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cfdp::VarLenField::setWidth(cfdp::WidthInBytes width_) { this->width = width_; }
|
|
||||||
|
@ -31,9 +31,7 @@ class VarLenField : public SerializeIF {
|
|||||||
bool operator!=(const VarLenField &other) const;
|
bool operator!=(const VarLenField &other) const;
|
||||||
bool operator<(const VarLenField &other) const;
|
bool operator<(const VarLenField &other) const;
|
||||||
|
|
||||||
ReturnValue_t setValueAndWidth(cfdp::WidthInBytes width, uint64_t value);
|
ReturnValue_t setValue(cfdp::WidthInBytes, uint64_t value);
|
||||||
void setWidth(cfdp::WidthInBytes width);
|
|
||||||
ReturnValue_t setValue(uint64_t value);
|
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override;
|
Endianness streamEndianness) const override;
|
||||||
@ -53,9 +51,9 @@ class VarLenField : public SerializeIF {
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the
|
using SerializeIF::deSerialize;
|
||||||
// compiler
|
|
||||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
@ -67,7 +65,7 @@ template <typename T>
|
|||||||
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
|
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
|
||||||
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
|
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
|
||||||
static_assert((sizeof(T) % 2) == 0);
|
static_assert((sizeof(T) % 2) == 0);
|
||||||
setValueAndWidth(width, byteField.getValue());
|
setValue(width, byteField.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EntityId : public VarLenField {
|
struct EntityId : public VarLenField {
|
||||||
@ -76,32 +74,6 @@ struct EntityId : public VarLenField {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
explicit EntityId(UnsignedByteField<T> byteField) : VarLenField(byteField) {}
|
explicit EntityId(UnsignedByteField<T> byteField) : VarLenField(byteField) {}
|
||||||
EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {}
|
EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {}
|
||||||
|
|
||||||
ReturnValue_t serializeAsLv(uint8_t **buffer, size_t *size, size_t maxSize) const {
|
|
||||||
if (buffer == nullptr or size == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
if (*size + 1 + getWidth() > maxSize) {
|
|
||||||
return SerializeIF::BUFFER_TOO_SHORT;
|
|
||||||
}
|
|
||||||
**buffer = getWidth();
|
|
||||||
*buffer += 1;
|
|
||||||
*size += 1;
|
|
||||||
return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t deSerializeFromLv(const uint8_t **buffer, size_t *deserLen) {
|
|
||||||
if (buffer == nullptr or deserLen == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
if (*deserLen < 2) {
|
|
||||||
return SerializeIF::STREAM_TOO_SHORT;
|
|
||||||
}
|
|
||||||
auto width = static_cast<WidthInBytes>(**buffer);
|
|
||||||
*buffer += 1;
|
|
||||||
*deserLen -= 1;
|
|
||||||
return VarLenField::deSerialize(width, buffer, deserLen, SerializeIF::Endianness::NETWORK);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransactionSeqNum : public VarLenField {
|
struct TransactionSeqNum : public VarLenField {
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
#include "fsfw/returnvalues/FwClassIds.h"
|
#include "fsfw/returnvalues/FwClassIds.h"
|
||||||
#include "fsfw/returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/returnvalue.h"
|
||||||
|
|
||||||
|
// Thanks, windows
|
||||||
|
#ifdef NO_ERROR
|
||||||
|
#undef NO_ERROR
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace cfdp {
|
namespace cfdp {
|
||||||
|
|
||||||
static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
|
static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
|
||||||
@ -17,7 +22,7 @@ static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
|
|||||||
static constexpr uint8_t CFDP_VERSION_2 = 0b001;
|
static constexpr uint8_t CFDP_VERSION_2 = 0b001;
|
||||||
static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5;
|
static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5;
|
||||||
|
|
||||||
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP_BASE;
|
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP;
|
||||||
|
|
||||||
static constexpr ReturnValue_t INVALID_TLV_TYPE = returnvalue::makeCode(CFDP_CLASS_ID, 1);
|
static constexpr ReturnValue_t INVALID_TLV_TYPE = returnvalue::makeCode(CFDP_CLASS_ID, 1);
|
||||||
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
|
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
|
||||||
@ -68,7 +73,6 @@ enum WidthInBytes : uint8_t {
|
|||||||
ONE_BYTE = 1,
|
ONE_BYTE = 1,
|
||||||
TWO_BYTES = 2,
|
TWO_BYTES = 2,
|
||||||
FOUR_BYTES = 4,
|
FOUR_BYTES = 4,
|
||||||
EIGHT_BYTES = 8
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileDirective : uint8_t {
|
enum FileDirective : uint8_t {
|
||||||
@ -143,20 +147,6 @@ enum RecordContinuationState {
|
|||||||
CONTAINS_START_AND_END = 0b11
|
CONTAINS_START_AND_END = 0b11
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ProxyOpMessageType : uint8_t {
|
|
||||||
PUT_REQUEST = 0x00,
|
|
||||||
MSG_TO_USR = 0x01,
|
|
||||||
FS_REQUEST = 0x02,
|
|
||||||
FAULT_HANDLER_OVERRIDE = 0x03,
|
|
||||||
TRANSMISSION_MODE = 0x04,
|
|
||||||
FLOW_LABEL = 0x05,
|
|
||||||
SEG_CTRL = 0x06,
|
|
||||||
PUT_RESPONSE = 0x07,
|
|
||||||
FS_RESPONSE = 0x08,
|
|
||||||
PUT_CANCEL = 0x09,
|
|
||||||
CLOSURE = 0x0b
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cfdp
|
} // namespace cfdp
|
||||||
|
|
||||||
#endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */
|
#endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */
|
||||||
|
@ -1,4 +1 @@
|
|||||||
target_sources(
|
target_sources(${LIB_FSFW_NAME} PRIVATE FaultHandlerBase.cpp UserBase.cpp)
|
||||||
${LIB_FSFW_NAME}
|
|
||||||
PRIVATE SourceHandler.cpp DestHandler.cpp PutRequest.cpp
|
|
||||||
ReservedMessageParser.cpp FaultHandlerBase.cpp UserBase.cpp)
|
|
||||||
|
@ -1,574 +0,0 @@
|
|||||||
#include "DestHandler.h"
|
|
||||||
|
|
||||||
#include <etl/crc32.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "fsfw/FSFW.h"
|
|
||||||
#include "fsfw/cfdp/pdu/EofPduReader.h"
|
|
||||||
#include "fsfw/cfdp/pdu/FileDataReader.h"
|
|
||||||
#include "fsfw/cfdp/pdu/FinishedPduCreator.h"
|
|
||||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
|
||||||
#include "fsfw/objectmanager.h"
|
|
||||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
|
||||||
|
|
||||||
using namespace returnvalue;
|
|
||||||
|
|
||||||
cfdp::DestHandler::DestHandler(DestHandlerParams params, FsfwParams fsfwParams)
|
|
||||||
: tlvVec(params.maxTlvsInOnePdu),
|
|
||||||
msgToUserVec(params.maxTlvsInOnePdu),
|
|
||||||
transactionParams(params.maxFilenameLen),
|
|
||||||
destParams(std::move(params)),
|
|
||||||
fsfwParams(fsfwParams) {
|
|
||||||
transactionParams.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::stateMachine() {
|
|
||||||
ReturnValue_t result;
|
|
||||||
uint8_t errorIdx = 0;
|
|
||||||
fsmRes.resetOfIteration();
|
|
||||||
if (fsmRes.step == TransactionStep::IDLE) {
|
|
||||||
for (auto infoIter = destParams.packetListRef.begin();
|
|
||||||
infoIter != destParams.packetListRef.end();) {
|
|
||||||
if (infoIter->pduType == PduType::FILE_DIRECTIVE and
|
|
||||||
infoIter->directiveType == FileDirective::METADATA) {
|
|
||||||
result = handleMetadataPdu(*infoIter);
|
|
||||||
checkAndHandleError(result, errorIdx);
|
|
||||||
// Store data was deleted in PDU handler because a store guard is used
|
|
||||||
destParams.packetListRef.erase(infoIter++);
|
|
||||||
} else {
|
|
||||||
infoIter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fsmRes.step == TransactionStep::IDLE) {
|
|
||||||
// To decrease the already high complexity of the software, all packets arriving before
|
|
||||||
// a metadata PDU are deleted.
|
|
||||||
for (auto infoIter = destParams.packetListRef.begin();
|
|
||||||
infoIter != destParams.packetListRef.end();) {
|
|
||||||
fsfwParams.tcStore->deleteData(infoIter->storeId);
|
|
||||||
infoIter++;
|
|
||||||
}
|
|
||||||
destParams.packetListRef.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsmRes.step != TransactionStep::IDLE) {
|
|
||||||
fsmRes.callStatus = CallStatus::CALL_AGAIN;
|
|
||||||
}
|
|
||||||
return updateFsmRes(errorIdx);
|
|
||||||
}
|
|
||||||
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
|
|
||||||
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
|
|
||||||
for (auto infoIter = destParams.packetListRef.begin();
|
|
||||||
infoIter != destParams.packetListRef.end();) {
|
|
||||||
if (infoIter->pduType == PduType::FILE_DATA) {
|
|
||||||
result = handleFileDataPdu(*infoIter);
|
|
||||||
checkAndHandleError(result, errorIdx);
|
|
||||||
// Store data was deleted in PDU handler because a store guard is used
|
|
||||||
destParams.packetListRef.erase(infoIter++);
|
|
||||||
} else if (infoIter->pduType == PduType::FILE_DIRECTIVE and
|
|
||||||
infoIter->directiveType == FileDirective::EOF_DIRECTIVE) {
|
|
||||||
// TODO: Support for check timer missing
|
|
||||||
result = handleEofPdu(*infoIter);
|
|
||||||
checkAndHandleError(result, errorIdx);
|
|
||||||
// Store data was deleted in PDU handler because a store guard is used
|
|
||||||
destParams.packetListRef.erase(infoIter++);
|
|
||||||
} else {
|
|
||||||
infoIter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fsmRes.step == TransactionStep::TRANSFER_COMPLETION) {
|
|
||||||
result = handleTransferCompletion();
|
|
||||||
checkAndHandleError(result, errorIdx);
|
|
||||||
}
|
|
||||||
if (fsmRes.step == TransactionStep::SENDING_FINISHED_PDU) {
|
|
||||||
result = sendFinishedPdu();
|
|
||||||
checkAndHandleError(result, errorIdx);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
return updateFsmRes(errorIdx);
|
|
||||||
}
|
|
||||||
if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
|
|
||||||
// TODO: Will be implemented at a later stage
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "CFDP state machine for acknowledged mode not implemented yet" << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return updateFsmRes(errorIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::passPacket(PacketInfo packet) {
|
|
||||||
if (destParams.packetListRef.full()) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
destParams.packetListRef.push_back(packet);
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::initialize() {
|
|
||||||
if (fsfwParams.tmStore == nullptr) {
|
|
||||||
fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
|
|
||||||
if (fsfwParams.tmStore == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsfwParams.tcStore == nullptr) {
|
|
||||||
fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
|
||||||
if (fsfwParams.tcStore == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsfwParams.msgQueue == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
|
|
||||||
// Process metadata PDU
|
|
||||||
auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
|
|
||||||
if (constAccessorPair.first != OK) {
|
|
||||||
// TODO: This is not a CFDP error. Event and/or warning?
|
|
||||||
return constAccessorPair.first;
|
|
||||||
}
|
|
||||||
cfdp::StringLv sourceFileName;
|
|
||||||
cfdp::StringLv destFileName;
|
|
||||||
MetadataGenericInfo metadataInfo(transactionParams.fileSize);
|
|
||||||
MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(),
|
|
||||||
metadataInfo, tlvVec.data(), tlvVec.size());
|
|
||||||
ReturnValue_t result = reader.parseData();
|
|
||||||
// TODO: The standard does not really specify what happens if this kind of error happens
|
|
||||||
// I think it might be a good idea to cache some sort of error code, which
|
|
||||||
// is translated into a warning and/or event by an upper layer
|
|
||||||
if (result != OK) {
|
|
||||||
return handleMetadataParseError(result, constAccessorPair.second.data(),
|
|
||||||
constAccessorPair.second.size());
|
|
||||||
}
|
|
||||||
return startTransaction(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
|
|
||||||
// Process file data PDU
|
|
||||||
auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
|
|
||||||
if (constAccessorPair.first != OK) {
|
|
||||||
// TODO: This is not a CFDP error. Event and/or warning?
|
|
||||||
return constAccessorPair.first;
|
|
||||||
}
|
|
||||||
FileDataInfo fdInfo;
|
|
||||||
FileDataReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), fdInfo);
|
|
||||||
ReturnValue_t result = reader.parseData();
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
size_t fileSegmentLen = 0;
|
|
||||||
const uint8_t* fileData = fdInfo.getFileData(&fileSegmentLen);
|
|
||||||
FileOpParams fileOpParams(transactionParams.destName.data(), fileSegmentLen);
|
|
||||||
fileOpParams.offset = fdInfo.getOffset().value();
|
|
||||||
if (destParams.cfg.indicCfg.fileSegmentRecvIndicRequired) {
|
|
||||||
FileSegmentRecvdParams segParams;
|
|
||||||
segParams.offset = fdInfo.getOffset().value();
|
|
||||||
segParams.id = transactionParams.transactionId;
|
|
||||||
segParams.length = fileSegmentLen;
|
|
||||||
segParams.recContState = fdInfo.getRecordContinuationState();
|
|
||||||
size_t segmentMetadatLen = 0;
|
|
||||||
auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen);
|
|
||||||
segParams.segmentMetadata = {segMetadata, segmentMetadatLen};
|
|
||||||
destParams.user.fileSegmentRecvdIndication(segParams);
|
|
||||||
}
|
|
||||||
result = destParams.user.vfs.writeToFile(fileOpParams, fileData);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
// TODO: Proper Error handling
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
|
|
||||||
<< result << std::endl;
|
|
||||||
#endif
|
|
||||||
transactionParams.vfsErrorCount++;
|
|
||||||
if (transactionParams.vfsErrorCount < 3) {
|
|
||||||
// TODO: Provide execution step as parameter
|
|
||||||
fsfwParams.eventReporter->forwardEvent(events::FILESTORE_ERROR,
|
|
||||||
static_cast<uint8_t>(fsmRes.step), result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
transactionParams.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
|
|
||||||
transactionParams.vfsErrorCount = 0;
|
|
||||||
}
|
|
||||||
if (fdInfo.getOffset().value() + fileSegmentLen > transactionParams.progress) {
|
|
||||||
transactionParams.progress = fdInfo.getOffset().value() + fileSegmentLen;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
|
|
||||||
// Process EOF PDU
|
|
||||||
auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
|
|
||||||
if (constAccessorPair.first != OK) {
|
|
||||||
// TODO: This is not a CFDP error. Event and/or warning?
|
|
||||||
return constAccessorPair.first;
|
|
||||||
}
|
|
||||||
EofInfo eofInfo(nullptr);
|
|
||||||
EofPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), eofInfo);
|
|
||||||
ReturnValue_t result = reader.parseData();
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// TODO: Error handling
|
|
||||||
if (eofInfo.getConditionCode() == ConditionCode::NO_ERROR) {
|
|
||||||
transactionParams.crc = eofInfo.getChecksum();
|
|
||||||
uint64_t fileSizeFromEof = eofInfo.getFileSize().value();
|
|
||||||
// CFDP 4.6.1.2.9: Declare file size error if progress exceeds file size
|
|
||||||
if (fileSizeFromEof > transactionParams.progress) {
|
|
||||||
// TODO: File size error
|
|
||||||
}
|
|
||||||
transactionParams.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
|
|
||||||
}
|
|
||||||
if (destParams.cfg.indicCfg.eofRecvIndicRequired) {
|
|
||||||
destParams.user.eofRecvIndication(getTransactionId());
|
|
||||||
}
|
|
||||||
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
|
|
||||||
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
|
|
||||||
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
|
|
||||||
} else if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
|
|
||||||
fsmRes.step = TransactionStep::SENDING_ACK_PDU;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::handleMetadataParseError(ReturnValue_t result,
|
|
||||||
const uint8_t* rawData, size_t maxSize) {
|
|
||||||
// TODO: try to extract destination ID for error
|
|
||||||
// TODO: Invalid metadata PDU.
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "Parsing Metadata PDU failed with code " << result << std::endl;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
PduHeaderReader headerReader(rawData, maxSize);
|
|
||||||
result = headerReader.parseData();
|
|
||||||
if (result != OK) {
|
|
||||||
// TODO: Now this really should not happen. Warning or error,
|
|
||||||
// yield or cache appropriate returnvalue
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "Parsing Header failed" << std::endl;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
// TODO: Trigger appropriate event
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
cfdp::EntityId destId;
|
|
||||||
headerReader.getDestId(destId);
|
|
||||||
RemoteEntityCfg* remoteCfg;
|
|
||||||
if (not destParams.remoteCfgTable.getRemoteCfg(destId, &remoteCfg)) {
|
|
||||||
// TODO: No remote config for dest ID. I consider this a configuration error, which is not
|
|
||||||
// covered by the standard.
|
|
||||||
// Warning or error, yield or cache appropriate returnvalue
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "No remote config exists for destination ID" << std::endl;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
// TODO: Trigger appropriate event
|
|
||||||
}
|
|
||||||
// TODO: Appropriate returnvalue?
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::startTransaction(const MetadataPduReader& reader) {
|
|
||||||
if (fsmRes.state != CfdpState::IDLE) {
|
|
||||||
// According to standard, discard metadata PDU if we are busy
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
ReturnValue_t result = OK;
|
|
||||||
size_t sourceNameSize = 0;
|
|
||||||
|
|
||||||
if (not reader.getSourceFileName().isEmpty()) {
|
|
||||||
const uint8_t* sourceNamePtr = reader.getSourceFileName().getValue(&sourceNameSize);
|
|
||||||
if (sourceNameSize + 1 > transactionParams.sourceName.size()) {
|
|
||||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
std::memcpy(transactionParams.sourceName.data(), sourceNamePtr, sourceNameSize);
|
|
||||||
transactionParams.sourceName[sourceNameSize] = '\0';
|
|
||||||
}
|
|
||||||
size_t destNameSize = 0;
|
|
||||||
if (not reader.getDestFileName().isEmpty()) {
|
|
||||||
const uint8_t* destNamePtr = reader.getDestFileName().getValue(&destNameSize);
|
|
||||||
if (destNameSize + 1 > transactionParams.destName.size()) {
|
|
||||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
std::memcpy(transactionParams.destName.data(), destNamePtr, destNameSize);
|
|
||||||
transactionParams.destName[destNameSize] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionParams.metadataOnly = true;
|
|
||||||
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
|
|
||||||
// so there is no need to create a file or truncate an existing file
|
|
||||||
if (destNameSize > 0 and sourceNameSize > 0) {
|
|
||||||
transactionParams.metadataOnly = false;
|
|
||||||
FilesystemParams fparams(transactionParams.destName.data());
|
|
||||||
// handling to allow only specifying target directory. Example:
|
|
||||||
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
|
|
||||||
if (destParams.user.vfs.isDirectory(transactionParams.destName.data())) {
|
|
||||||
result = tryBuildingAbsoluteDestName(destNameSize);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (destParams.user.vfs.fileExists(fparams)) {
|
|
||||||
result = destParams.user.vfs.truncateFile(fparams);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
|
|
||||||
return FAILED;
|
|
||||||
// TODO: Relevant for filestore rejection error?
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = destParams.user.vfs.createFile(fparams);
|
|
||||||
if (result != OK) {
|
|
||||||
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
|
|
||||||
return FAILED;
|
|
||||||
// TODO: Relevant for filestore rejection error?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EntityId sourceId;
|
|
||||||
reader.getSourceId(sourceId);
|
|
||||||
if (not destParams.remoteCfgTable.getRemoteCfg(sourceId, &transactionParams.remoteCfg)) {
|
|
||||||
// TODO: Warning, event etc.
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "cfdp::DestHandler" << __func__
|
|
||||||
<< ": No remote configuration found for destination ID "
|
|
||||||
<< transactionParams.pduConf.sourceId.getValue() << std::endl;
|
|
||||||
#endif
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
|
|
||||||
fsmRes.state = CfdpState::BUSY_CLASS_1_NACKED;
|
|
||||||
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
|
|
||||||
fsmRes.state = CfdpState::BUSY_CLASS_2_ACKED;
|
|
||||||
}
|
|
||||||
if (transactionParams.metadataOnly) {
|
|
||||||
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
|
|
||||||
} else {
|
|
||||||
// Kind of ugly, make FSM working on packet per packet basis..
|
|
||||||
fsmRes.step = TransactionStep::TRANSACTION_START;
|
|
||||||
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
|
|
||||||
}
|
|
||||||
auto& info = reader.getGenericInfo();
|
|
||||||
transactionParams.checksumType = info.getChecksumType();
|
|
||||||
transactionParams.closureRequested = info.isClosureRequested();
|
|
||||||
reader.fillConfig(transactionParams.pduConf);
|
|
||||||
transactionParams.pduConf.direction = Direction::TOWARDS_SENDER;
|
|
||||||
transactionParams.transactionId.entityId = transactionParams.pduConf.sourceId;
|
|
||||||
transactionParams.transactionId.seqNum = transactionParams.pduConf.seqNum;
|
|
||||||
transactionParams.fileSize = info.getFileSize();
|
|
||||||
MetadataRecvdParams params(transactionParams.transactionId, transactionParams.pduConf.sourceId,
|
|
||||||
transactionParams.fileSize);
|
|
||||||
params.destFileName = transactionParams.destName.data();
|
|
||||||
params.sourceFileName = transactionParams.sourceName.data();
|
|
||||||
params.numberOfMsgsToUser = 0;
|
|
||||||
for (const auto& opt : tlvVec) {
|
|
||||||
if (opt.getType() == TlvType::MSG_TO_USER) {
|
|
||||||
msgToUserVec[params.numberOfMsgsToUser] =
|
|
||||||
MessageToUserTlv(opt.getValue(), opt.getLengthField());
|
|
||||||
params.numberOfMsgsToUser++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
params.msgsToUserArray = msgToUserVec.data();
|
|
||||||
destParams.user.metadataRecvdIndication(params);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfdp::CfdpState cfdp::DestHandler::getCfdpState() const { return fsmRes.state; }
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
|
|
||||||
ReturnValue_t result;
|
|
||||||
if (transactionParams.checksumType != ChecksumType::NULL_CHECKSUM) {
|
|
||||||
result = checksumVerification();
|
|
||||||
if (result != OK) {
|
|
||||||
// TODO: Warning / error handling?
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
transactionParams.conditionCode = ConditionCode::NO_ERROR;
|
|
||||||
}
|
|
||||||
result = noticeOfCompletion();
|
|
||||||
if (result != OK) {
|
|
||||||
}
|
|
||||||
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
|
|
||||||
if (transactionParams.closureRequested) {
|
|
||||||
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
|
|
||||||
} else {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
} else if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
|
|
||||||
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
|
|
||||||
// A path may only have a maximum of 256 characters in CFDP, so this buffer should be sufficient
|
|
||||||
// for all use-cases.
|
|
||||||
char baseNameBuf[512]{};
|
|
||||||
FilesystemParams fparamsSrc(transactionParams.sourceName.data());
|
|
||||||
size_t baseNameLen = 0;
|
|
||||||
ReturnValue_t result = destParams.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf,
|
|
||||||
sizeof(baseNameBuf), baseNameLen);
|
|
||||||
if (result != returnvalue::OK or baseNameLen == 0) {
|
|
||||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
// Destination name + slash + base name + null termination
|
|
||||||
if (destNameSize + 1 + baseNameLen + 1 > transactionParams.destName.size()) {
|
|
||||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
|
|
||||||
"dest filename too large after adding source base name");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
transactionParams.destName[destNameSize++] = '/';
|
|
||||||
std::memcpy(transactionParams.destName.data() + destNameSize, baseNameBuf, baseNameLen);
|
|
||||||
destNameSize += baseNameLen;
|
|
||||||
transactionParams.destName[destNameSize++] = '\0';
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result,
|
|
||||||
const char* info) const {
|
|
||||||
fsfwParams.eventReporter->forwardEvent(event, static_cast<uint8_t>(fsmRes.step), result);
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "cfdp::DestHandler: " << info << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void cfdp::DestHandler::finish() {
|
|
||||||
transactionParams.reset();
|
|
||||||
destParams.packetListRef.clear();
|
|
||||||
fsmRes.state = CfdpState::IDLE;
|
|
||||||
fsmRes.step = TransactionStep::IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::checksumVerification() {
|
|
||||||
std::array<uint8_t, 1024> buf{};
|
|
||||||
etl::crc32 crcCalc;
|
|
||||||
uint64_t currentOffset = 0;
|
|
||||||
FileOpParams params(transactionParams.destName.data(), transactionParams.fileSize.value());
|
|
||||||
while (currentOffset < transactionParams.fileSize.value()) {
|
|
||||||
uint64_t readLen;
|
|
||||||
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
|
|
||||||
readLen = transactionParams.fileSize.value() - currentOffset;
|
|
||||||
} else {
|
|
||||||
readLen = buf.size();
|
|
||||||
}
|
|
||||||
if (readLen > 0) {
|
|
||||||
params.offset = currentOffset;
|
|
||||||
params.size = readLen;
|
|
||||||
auto result = destParams.user.vfs.readFromFile(params, buf.data(), buf.size());
|
|
||||||
if (result != OK) {
|
|
||||||
// TODO: I think this is a case for a filestore rejection, but it might sense to print
|
|
||||||
// a warning or trigger an event because this should generally not happen
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
crcCalc.add(buf.begin(), buf.begin() + readLen);
|
|
||||||
}
|
|
||||||
currentOffset += readLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t value = crcCalc.value();
|
|
||||||
if (value == transactionParams.crc) {
|
|
||||||
transactionParams.conditionCode = ConditionCode::NO_ERROR;
|
|
||||||
transactionParams.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
|
|
||||||
} else {
|
|
||||||
// TODO: Proper error handling
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "CRC check for file " << transactionParams.destName.data() << " failed"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
transactionParams.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::noticeOfCompletion() {
|
|
||||||
if (destParams.cfg.indicCfg.transactionFinishedIndicRequired) {
|
|
||||||
TransactionFinishedParams params(
|
|
||||||
transactionParams.transactionId, transactionParams.conditionCode,
|
|
||||||
transactionParams.deliveryCode, transactionParams.deliveryStatus);
|
|
||||||
destParams.user.transactionFinishedIndication(params);
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
|
|
||||||
FinishedInfo info(transactionParams.conditionCode, transactionParams.deliveryCode,
|
|
||||||
transactionParams.deliveryStatus);
|
|
||||||
FinishPduCreator finishedPdu(transactionParams.pduConf, info);
|
|
||||||
store_address_t storeId;
|
|
||||||
uint8_t* dataPtr = nullptr;
|
|
||||||
ReturnValue_t result =
|
|
||||||
fsfwParams.tmStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr);
|
|
||||||
if (result != OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "cfdp::DestHandler:sendFinishedPdu: Getting store slot failed" << std::endl;
|
|
||||||
#endif
|
|
||||||
fsfwParams.eventReporter->forwardEvent(events::STORE_ERROR, result, 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
size_t serLen = 0;
|
|
||||||
result = finishedPdu.serialize(dataPtr, serLen, finishedPdu.getSerializedSize());
|
|
||||||
if (result != OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Serializing Finished PDU failed"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
fsfwParams.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
TmTcMessage msg(storeId);
|
|
||||||
result = fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &msg);
|
|
||||||
if (result != OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl;
|
|
||||||
#endif
|
|
||||||
fsfwParams.eventReporter->forwardEvent(events::MSG_QUEUE_ERROR, result, 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
fsmRes.packetsSent++;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfdp::DestHandler::TransactionStep cfdp::DestHandler::getTransactionStep() const {
|
|
||||||
return fsmRes.step;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::updateFsmRes(uint8_t errors) {
|
|
||||||
fsmRes.errors = errors;
|
|
||||||
fsmRes.result = OK;
|
|
||||||
if (fsmRes.errors > 0) {
|
|
||||||
fsmRes.result = FAILED;
|
|
||||||
}
|
|
||||||
return fsmRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfdp::TransactionId& cfdp::DestHandler::getTransactionId() const {
|
|
||||||
return transactionParams.transactionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cfdp::DestHandler::checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx) {
|
|
||||||
if (result != OK and errorIdx < 3) {
|
|
||||||
fsmRes.errorCodes[errorIdx] = result;
|
|
||||||
errorIdx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cfdp::DestHandler::setMsgQueue(MessageQueueIF& queue) { fsfwParams.msgQueue = &queue; }
|
|
||||||
|
|
||||||
void cfdp::DestHandler::setEventReporter(EventReportingProxyIF& reporter) {
|
|
||||||
fsfwParams.eventReporter = &reporter;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const {
|
|
||||||
return destParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageManagerIF* cfdp::DestHandler::getTmStore() const { return fsfwParams.tmStore; }
|
|
||||||
StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fsfwParams.tcStore; }
|
|
@ -1,178 +0,0 @@
|
|||||||
#ifndef FSFW_CFDP_CFDPDESTHANDLER_H
|
|
||||||
#define FSFW_CFDP_CFDPDESTHANDLER_H
|
|
||||||
|
|
||||||
#include <etl/list.h>
|
|
||||||
#include <etl/set.h>
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <optional>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "RemoteConfigTableIF.h"
|
|
||||||
#include "UserBase.h"
|
|
||||||
#include "defs.h"
|
|
||||||
#include "fsfw/cfdp/handler/mib.h"
|
|
||||||
#include "fsfw/cfdp/pdu/MetadataPduReader.h"
|
|
||||||
#include "fsfw/cfdp/pdu/PduConfig.h"
|
|
||||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
|
||||||
#include "fsfw/container/DynamicFIFO.h"
|
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
|
||||||
#include "fsfw/storagemanager/storeAddress.h"
|
|
||||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
|
||||||
|
|
||||||
namespace cfdp {
|
|
||||||
|
|
||||||
template <size_t SIZE>
|
|
||||||
using LostSegmentsList = etl::set<etl::pair<uint64_t, uint64_t>, SIZE>;
|
|
||||||
using LostSegmentsListBase = etl::iset<etl::pair<uint64_t, uint64_t>>;
|
|
||||||
|
|
||||||
struct DestHandlerParams {
|
|
||||||
DestHandlerParams(LocalEntityCfg cfg, UserBase& user, RemoteConfigTableIF& remoteCfgTable,
|
|
||||||
PacketInfoListBase& packetList,
|
|
||||||
// TODO: This container can potentially take tons of space. For a better
|
|
||||||
// memory efficient implementation, an additional abstraction could be
|
|
||||||
// be used so users can use uint32_t as the pair type
|
|
||||||
// TODO: Actually, we can provide a better abstraction via interface, which
|
|
||||||
// allows using something like a bounded map. This simplifies
|
|
||||||
// the implementation significantly.
|
|
||||||
LostSegmentsListBase& lostSegmentsContainer)
|
|
||||||
: cfg(std::move(cfg)),
|
|
||||||
user(user),
|
|
||||||
remoteCfgTable(remoteCfgTable),
|
|
||||||
packetListRef(packetList),
|
|
||||||
lostSegmentsContainer(lostSegmentsContainer) {}
|
|
||||||
|
|
||||||
LocalEntityCfg cfg;
|
|
||||||
UserBase& user;
|
|
||||||
RemoteConfigTableIF& remoteCfgTable;
|
|
||||||
|
|
||||||
PacketInfoListBase& packetListRef;
|
|
||||||
LostSegmentsListBase& lostSegmentsContainer;
|
|
||||||
uint8_t maxTlvsInOnePdu = 20;
|
|
||||||
size_t maxFilenameLen = 255;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DestHandler {
|
|
||||||
public:
|
|
||||||
enum class TransactionStep : uint8_t {
|
|
||||||
IDLE = 0,
|
|
||||||
TRANSACTION_START = 1,
|
|
||||||
RECEIVING_FILE_DATA_PDUS = 2,
|
|
||||||
SENDING_ACK_PDU = 3,
|
|
||||||
TRANSFER_COMPLETION = 4,
|
|
||||||
SENDING_FINISHED_PDU = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FsmResult {
|
|
||||||
public:
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
||||||
TransactionStep step = TransactionStep::IDLE;
|
|
||||||
CfdpState state = CfdpState::IDLE;
|
|
||||||
uint32_t packetsSent = 0;
|
|
||||||
uint8_t errors = 0;
|
|
||||||
std::array<ReturnValue_t, 3> errorCodes = {};
|
|
||||||
void resetOfIteration() {
|
|
||||||
result = returnvalue::OK;
|
|
||||||
callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
||||||
packetsSent = 0;
|
|
||||||
errors = 0;
|
|
||||||
errorCodes.fill(returnvalue::OK);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Will be returned if it is advisable to call the state machine operation call again
|
|
||||||
*/
|
|
||||||
ReturnValue_t PARTIAL_SUCCESS = returnvalue::makeCode(0, 2);
|
|
||||||
ReturnValue_t FAILURE = returnvalue::makeCode(0, 3);
|
|
||||||
explicit DestHandler(DestHandlerParams handlerParams, FsfwParams fsfwParams);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - @c returnvalue::OK State machine OK for this execution cycle
|
|
||||||
* - @c CALL_FSM_AGAIN State machine should be called again.
|
|
||||||
*/
|
|
||||||
const FsmResult& stateMachine();
|
|
||||||
void setMsgQueue(MessageQueueIF& queue);
|
|
||||||
void setEventReporter(EventReportingProxyIF& reporter);
|
|
||||||
|
|
||||||
ReturnValue_t passPacket(PacketInfo packet);
|
|
||||||
|
|
||||||
ReturnValue_t initialize();
|
|
||||||
|
|
||||||
[[nodiscard]] CfdpState getCfdpState() const;
|
|
||||||
[[nodiscard]] TransactionStep getTransactionStep() const;
|
|
||||||
[[nodiscard]] const TransactionId& getTransactionId() const;
|
|
||||||
[[nodiscard]] const DestHandlerParams& getDestHandlerParams() const;
|
|
||||||
[[nodiscard]] StorageManagerIF* getTcStore() const;
|
|
||||||
[[nodiscard]] StorageManagerIF* getTmStore() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct TransactionParams {
|
|
||||||
// Initialize char vectors with length + 1 for 0 termination
|
|
||||||
explicit TransactionParams(size_t maxFileNameLen)
|
|
||||||
: sourceName(maxFileNameLen + 1), destName(maxFileNameLen + 1) {}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
pduConf = PduConfig();
|
|
||||||
transactionId = TransactionId();
|
|
||||||
std::fill(sourceName.begin(), sourceName.end(), '\0');
|
|
||||||
std::fill(destName.begin(), destName.end(), '\0');
|
|
||||||
fileSize.setFileSize(0, false);
|
|
||||||
conditionCode = ConditionCode::NO_ERROR;
|
|
||||||
deliveryCode = FileDeliveryCode::DATA_INCOMPLETE;
|
|
||||||
deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY;
|
|
||||||
crc = 0;
|
|
||||||
progress = 0;
|
|
||||||
remoteCfg = nullptr;
|
|
||||||
metadataOnly = false;
|
|
||||||
closureRequested = false;
|
|
||||||
vfsErrorCount = 0;
|
|
||||||
checksumType = ChecksumType::NULL_CHECKSUM;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool metadataOnly = false;
|
|
||||||
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
|
|
||||||
bool closureRequested = false;
|
|
||||||
uint16_t vfsErrorCount = 0;
|
|
||||||
std::vector<char> sourceName;
|
|
||||||
std::vector<char> destName;
|
|
||||||
cfdp::Fss fileSize;
|
|
||||||
TransactionId transactionId;
|
|
||||||
PduConfig pduConf;
|
|
||||||
ConditionCode conditionCode = ConditionCode::NO_ERROR;
|
|
||||||
FileDeliveryCode deliveryCode = FileDeliveryCode::DATA_INCOMPLETE;
|
|
||||||
FileDeliveryStatus deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY;
|
|
||||||
uint32_t crc = 0;
|
|
||||||
uint64_t progress = 0;
|
|
||||||
RemoteEntityCfg* remoteCfg = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<cfdp::Tlv> tlvVec;
|
|
||||||
std::vector<MessageToUserTlv> msgToUserVec;
|
|
||||||
TransactionParams transactionParams;
|
|
||||||
DestHandlerParams destParams;
|
|
||||||
cfdp::FsfwParams fsfwParams;
|
|
||||||
FsmResult fsmRes;
|
|
||||||
|
|
||||||
ReturnValue_t startTransaction(const MetadataPduReader& reader);
|
|
||||||
ReturnValue_t handleMetadataPdu(const PacketInfo& info);
|
|
||||||
ReturnValue_t handleFileDataPdu(const PacketInfo& info);
|
|
||||||
ReturnValue_t handleEofPdu(const PacketInfo& info);
|
|
||||||
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
|
|
||||||
size_t maxSize);
|
|
||||||
ReturnValue_t handleTransferCompletion();
|
|
||||||
ReturnValue_t tryBuildingAbsoluteDestName(size_t destNameSize);
|
|
||||||
ReturnValue_t sendFinishedPdu();
|
|
||||||
ReturnValue_t noticeOfCompletion();
|
|
||||||
ReturnValue_t checksumVerification();
|
|
||||||
void fileErrorHandler(Event event, ReturnValue_t result, const char* info) const;
|
|
||||||
const FsmResult& updateFsmRes(uint8_t errors);
|
|
||||||
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
|
|
||||||
void finish();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cfdp
|
|
||||||
|
|
||||||
#endif // FSFW_CFDP_CFDPDESTHANDLER_H
|
|
@ -1,201 +0,0 @@
|
|||||||
#include "PutRequest.h"
|
|
||||||
|
|
||||||
using namespace returnvalue;
|
|
||||||
|
|
||||||
cfdp::PutRequest::PutRequest(cfdp::EntityId destId, const uint8_t *msgsToUser,
|
|
||||||
size_t msgsToUserTotalSize, const uint8_t *fsRequests,
|
|
||||||
size_t fsRequestsSize)
|
|
||||||
: destId(std::move(destId)),
|
|
||||||
metadataOnly(true),
|
|
||||||
msgsToUsersTotalSize(msgsToUserTotalSize),
|
|
||||||
msgsToUserStartPtr(msgsToUser),
|
|
||||||
fsRequestsTotalSize(fsRequestsSize),
|
|
||||||
fsRequestStartPtr(fsRequests) {}
|
|
||||||
|
|
||||||
cfdp::PutRequest::PutRequest(cfdp::EntityId destId, cfdp::StringLv &sourceName,
|
|
||||||
cfdp::StringLv &destName)
|
|
||||||
: destId(std::move(destId)), sourceName(std::move(sourceName)), destName(std::move(destName)) {}
|
|
||||||
|
|
||||||
[[nodiscard]] bool cfdp::PutRequest::isMetadataOnly() const { return metadataOnly; }
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::PutRequest::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
|
||||||
SerializeIF::Endianness streamEndianness) const {
|
|
||||||
if (buffer == nullptr or size == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
if (*size + getSerializedSize() > maxSize) {
|
|
||||||
return SerializeIF::BUFFER_TOO_SHORT;
|
|
||||||
}
|
|
||||||
ReturnValue_t result = destId.serializeAsLv(buffer, size, maxSize);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::serialize(&metadataOnly, buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (!metadataOnly) {
|
|
||||||
result = sourceName.serialize(buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = destName.serialize(buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result =
|
|
||||||
SerializeAdapter::serialize(&hasTransmissionMode, buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result =
|
|
||||||
SerializeAdapter::serialize(&transmissionMode, buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result =
|
|
||||||
SerializeAdapter::serialize(&hasClosureRequested, buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result =
|
|
||||||
SerializeAdapter::serialize(&closureRequested, buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result =
|
|
||||||
SerializeAdapter::serialize(&msgsToUsersTotalSize, buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
std::memcpy(*buffer, msgsToUserStartPtr, msgsToUsersTotalSize);
|
|
||||||
*buffer += msgsToUsersTotalSize;
|
|
||||||
*size += msgsToUsersTotalSize;
|
|
||||||
|
|
||||||
result =
|
|
||||||
SerializeAdapter::serialize(&fsRequestsTotalSize, buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
std::memcpy(*buffer, fsRequestStartPtr, fsRequestsTotalSize);
|
|
||||||
*buffer += fsRequestsTotalSize;
|
|
||||||
*size += fsRequestsTotalSize;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::PutRequest::deSerialize(const uint8_t **buffer, size_t *size,
|
|
||||||
SerializeIF::Endianness streamEndianness) {
|
|
||||||
if (buffer == nullptr or size == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
ReturnValue_t result = destId.deSerializeFromLv(buffer, size);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&metadataOnly, buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (!metadataOnly) {
|
|
||||||
result = sourceName.deSerialize(buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = destName.deSerialize(buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&hasTransmissionMode, buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&transmissionMode, buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&hasClosureRequested, buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&closureRequested, buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&msgsToUsersTotalSize, buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
msgsToUserStartPtr = *buffer;
|
|
||||||
*buffer += msgsToUsersTotalSize;
|
|
||||||
*size += msgsToUsersTotalSize;
|
|
||||||
|
|
||||||
result = SerializeAdapter::deSerialize(&fsRequestsTotalSize, buffer, size, streamEndianness);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
fsRequestStartPtr = *buffer;
|
|
||||||
*buffer += fsRequestsTotalSize;
|
|
||||||
*size += fsRequestsTotalSize;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cfdp::PutRequest::getSerializedSize() const {
|
|
||||||
// Entity ID LV (1 leading size byte) and the metadata only flag.
|
|
||||||
size_t baseSize = 1 + destId.getSerializedSize() + 1;
|
|
||||||
if (!metadataOnly) {
|
|
||||||
baseSize += sourceName.getSerializedSize() + destName.getSerializedSize() + 4;
|
|
||||||
}
|
|
||||||
baseSize += sizeof(msgsToUsersTotalSize) + msgsToUsersTotalSize + sizeof(fsRequestsTotalSize) +
|
|
||||||
fsRequestsTotalSize;
|
|
||||||
return baseSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cfdp::PutRequest::setSourceAndDestName(cfdp::StringLv &sourceName_,
|
|
||||||
cfdp::StringLv &destName_) {
|
|
||||||
metadataOnly = false;
|
|
||||||
this->sourceName = std::move(sourceName_);
|
|
||||||
this->destName = std::move(destName_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfdp::StringLv &cfdp::PutRequest::getSourceName() const { return sourceName; }
|
|
||||||
|
|
||||||
const cfdp::StringLv &cfdp::PutRequest::getDestName() const { return destName; }
|
|
||||||
|
|
||||||
const cfdp::EntityId &cfdp::PutRequest::getDestId() const { return destId; }
|
|
||||||
|
|
||||||
void cfdp::PutRequest::setDestId(cfdp::EntityId id) { destId = std::move(id); }
|
|
||||||
|
|
||||||
void cfdp::PutRequest::setTransmissionMode(cfdp::TransmissionMode transmissionMode_) {
|
|
||||||
this->transmissionMode = transmissionMode_;
|
|
||||||
hasTransmissionMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cfdp::PutRequest::clearTransmissionMode() { hasTransmissionMode = false; }
|
|
||||||
|
|
||||||
void cfdp::PutRequest::clearClosureRequest() { hasClosureRequested = false; }
|
|
||||||
|
|
||||||
void cfdp::PutRequest::setClosureRequest(bool closureRequested_) {
|
|
||||||
this->closureRequested = closureRequested_;
|
|
||||||
hasClosureRequested = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t *cfdp::PutRequest::getMessagesToUser(size_t &totalSize) {
|
|
||||||
totalSize = this->msgsToUsersTotalSize;
|
|
||||||
return msgsToUserStartPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cfdp::PutRequest::getClosureRequested(bool &closureRequested_) const {
|
|
||||||
if (hasClosureRequested) {
|
|
||||||
closureRequested_ = this->closureRequested;
|
|
||||||
}
|
|
||||||
return hasClosureRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cfdp::PutRequest::getTransmissionMode(cfdp::TransmissionMode &mode) const {
|
|
||||||
if (hasTransmissionMode) {
|
|
||||||
mode = static_cast<cfdp::TransmissionMode>(this->transmissionMode);
|
|
||||||
}
|
|
||||||
return hasTransmissionMode;
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "fsfw/cfdp/VarLenFields.h"
|
|
||||||
#include "fsfw/cfdp/tlv/FilestoreRequestTlv.h"
|
|
||||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
|
||||||
|
|
||||||
namespace cfdp {
|
|
||||||
|
|
||||||
class PutRequest : public SerializeIF {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Metadata only constructor.
|
|
||||||
* @param destId
|
|
||||||
* @param msgsToUser
|
|
||||||
* @param msgsToUserTotalSize
|
|
||||||
* @param fsRequests
|
|
||||||
* @param fsRequestsSize
|
|
||||||
*/
|
|
||||||
PutRequest(EntityId destId, const uint8_t* msgsToUser, size_t msgsToUserTotalSize,
|
|
||||||
const uint8_t* fsRequests, size_t fsRequestsSize);
|
|
||||||
/**
|
|
||||||
* Put request to initiate file transfers. By default, the transmission mode and closure requested
|
|
||||||
* parameter are not present, thereby being derived from the remote configuration for a
|
|
||||||
* particular destination ID.
|
|
||||||
* @param destId
|
|
||||||
* @param sourceName
|
|
||||||
* @param destName
|
|
||||||
*/
|
|
||||||
PutRequest(EntityId destId, cfdp::StringLv& sourceName, cfdp::StringLv& destName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor for deserialization.
|
|
||||||
*/
|
|
||||||
PutRequest() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
|
||||||
Endianness streamEndianness) const override;
|
|
||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
|
||||||
Endianness streamEndianness) override;
|
|
||||||
[[nodiscard]] size_t getSerializedSize() const override;
|
|
||||||
void setSourceAndDestName(cfdp::StringLv& sourceName, cfdp::StringLv& destName);
|
|
||||||
|
|
||||||
[[nodiscard]] const cfdp::StringLv& getSourceName() const;
|
|
||||||
[[nodiscard]] const cfdp::StringLv& getDestName() const;
|
|
||||||
|
|
||||||
void setTransmissionMode(cfdp::TransmissionMode transmissionMode);
|
|
||||||
void clearTransmissionMode();
|
|
||||||
void setClosureRequest(bool closureRequested);
|
|
||||||
void clearClosureRequest();
|
|
||||||
|
|
||||||
const uint8_t* getMessagesToUser(size_t& msgSize);
|
|
||||||
|
|
||||||
[[nodiscard]] bool isMetadataOnly() const;
|
|
||||||
|
|
||||||
bool getTransmissionMode(TransmissionMode& mode) const;
|
|
||||||
bool getClosureRequested(bool& closureRequested) const;
|
|
||||||
|
|
||||||
[[nodiscard]] const EntityId& getDestId() const;
|
|
||||||
void setDestId(EntityId id);
|
|
||||||
|
|
||||||
private:
|
|
||||||
EntityId destId;
|
|
||||||
uint8_t metadataOnly = true;
|
|
||||||
// Transaction parameters. Omitted if the put request is metadata only.
|
|
||||||
cfdp::StringLv sourceName;
|
|
||||||
|
|
||||||
cfdp::StringLv destName;
|
|
||||||
bool hasTransmissionMode = false;
|
|
||||||
uint8_t transmissionMode = TransmissionMode::UNACKNOWLEDGED;
|
|
||||||
bool hasClosureRequested = false;
|
|
||||||
uint8_t closureRequested = false;
|
|
||||||
// Metadata
|
|
||||||
size_t msgsToUsersTotalSize = 0;
|
|
||||||
const uint8_t* msgsToUserStartPtr = nullptr;
|
|
||||||
size_t fsRequestsTotalSize = 0;
|
|
||||||
const uint8_t* fsRequestStartPtr = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cfdp
|
|
@ -16,7 +16,7 @@ class RemoteConfigTableIF {
|
|||||||
*/
|
*/
|
||||||
class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
||||||
public:
|
public:
|
||||||
explicit OneRemoteConfigProvider(RemoteEntityCfg& cfg) : cfg(cfg) {}
|
explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {}
|
||||||
|
|
||||||
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
|
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
|
||||||
if (remoteId != cfg.remoteId) {
|
if (remoteId != cfg.remoteId) {
|
||||||
@ -27,7 +27,7 @@ class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RemoteEntityCfg& cfg;
|
RemoteEntityCfg cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cfdp
|
} // namespace cfdp
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
#include "ReservedMessageParser.h"
|
|
||||||
|
|
||||||
#include "fsfw/cfdp/CfdpMessage.h"
|
|
||||||
#include "fsfw/cfdp/handler/PutRequest.h"
|
|
||||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
|
||||||
#include "fsfw/ipc/CommandMessage.h"
|
|
||||||
#include "fsfw/ipc/QueueFactory.h"
|
|
||||||
|
|
||||||
using namespace returnvalue;
|
|
||||||
|
|
||||||
cfdp::ReservedMessageParser::ReservedMessageParser(StorageManagerIF& ipcStore,
|
|
||||||
MessageQueueIF& msgQueue,
|
|
||||||
MessageQueueId_t userDestination)
|
|
||||||
: msgQueue(msgQueue), ipcStore(ipcStore), userDestination(userDestination) {}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::ReservedMessageParser::parse(const MessageToUserTlv* msgsToUserArray,
|
|
||||||
size_t numMsgToUser) {
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
cfdp::StringLv sourceFileName;
|
|
||||||
cfdp::StringLv destFileName;
|
|
||||||
PutRequest putRequest;
|
|
||||||
const uint8_t* currentPtr = nullptr;
|
|
||||||
size_t deserSize = 0;
|
|
||||||
bool needToSendPutRequest = false;
|
|
||||||
for (size_t idx = 0; idx < numMsgToUser; idx++) {
|
|
||||||
if (&msgsToUserArray[idx] == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
uint8_t messageType = 0;
|
|
||||||
if (msgsToUserArray[idx].isReservedCfdpMessage(messageType, ¤tPtr, deserSize)) {
|
|
||||||
if (messageType == static_cast<uint8_t>(ProxyOpMessageType::PUT_REQUEST)) {
|
|
||||||
EntityId entityIdLv;
|
|
||||||
result = entityIdLv.deSerializeFromLv(¤tPtr, &deserSize);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
putRequest.setDestId(entityIdLv);
|
|
||||||
result =
|
|
||||||
sourceFileName.deSerialize(¤tPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result =
|
|
||||||
destFileName.deSerialize(¤tPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
putRequest.setSourceAndDestName(sourceFileName, destFileName);
|
|
||||||
needToSendPutRequest = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (needToSendPutRequest) {
|
|
||||||
store_address_t storeId;
|
|
||||||
uint8_t* dataPtr;
|
|
||||||
result = ipcStore.getFreeElement(&storeId, putRequest.getSerializedSize(), &dataPtr);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
size_t serLen = 0;
|
|
||||||
result = putRequest.serialize(&dataPtr, &serLen, putRequest.getSerializedSize(),
|
|
||||||
SerializeIF::Endianness::MACHINE);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
CommandMessage msg;
|
|
||||||
CfdpMessage::setPutRequest(&msg, storeId);
|
|
||||||
result = msgQueue.sendMessage(userDestination, &msg);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
|
||||||
|
|
||||||
namespace cfdp {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class parses messages to user for special CFDP messages and converts them to appropriate
|
|
||||||
* CFDP requests sent via the IPC store where applicable. It also provides an API to retrieve
|
|
||||||
* custom messages which are not special CFDP messages from a provided bytestream.
|
|
||||||
*/
|
|
||||||
class ReservedMessageParser {
|
|
||||||
public:
|
|
||||||
ReservedMessageParser(StorageManagerIF& ipcStore, MessageQueueIF& msgQueue,
|
|
||||||
MessageQueueId_t userDestination);
|
|
||||||
|
|
||||||
ReturnValue_t parse(const MessageToUserTlv* msgsToUserArray, size_t numMsgsToUser);
|
|
||||||
|
|
||||||
private:
|
|
||||||
MessageQueueIF& msgQueue;
|
|
||||||
StorageManagerIF& ipcStore;
|
|
||||||
MessageQueueId_t userDestination;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cfdp
|
|
@ -1,376 +0,0 @@
|
|||||||
#include "SourceHandler.h"
|
|
||||||
|
|
||||||
#include <etl/crc32.h>
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
|
||||||
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
|
||||||
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
|
||||||
#include "fsfw/filesystem/HasFileSystemIF.h"
|
|
||||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
|
||||||
#include "fsfw/objectmanager.h"
|
|
||||||
#include "fsfw/serviceinterface.h"
|
|
||||||
#include "fsfw/tasks/TaskFactory.h"
|
|
||||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
|
||||||
|
|
||||||
using namespace returnvalue;
|
|
||||||
|
|
||||||
cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams)
|
|
||||||
: sourceParams(std::move(params)), fsfwParams(fsfwParams) {
|
|
||||||
// The entity ID portion of the transaction ID will always remain fixed.
|
|
||||||
transactionParams.id.entityId = sourceParams.cfg.localId;
|
|
||||||
transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
|
|
||||||
if (sourceParams.seqCountProvider.bitWidth() == 8) {
|
|
||||||
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
|
|
||||||
} else if (sourceParams.seqCountProvider.bitWidth() == 16) {
|
|
||||||
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::TWO_BYTES);
|
|
||||||
} else if (sourceParams.seqCountProvider.bitWidth() == 32) {
|
|
||||||
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::FOUR_BYTES);
|
|
||||||
} else if (sourceParams.seqCountProvider.bitWidth() == 64) {
|
|
||||||
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::EIGHT_BYTES);
|
|
||||||
} else {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "cfdp::SourceHandler: Seq count provider bit width "
|
|
||||||
<< sourceParams.seqCountProvider.bitWidth() << " not allowed" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError("cfdp::SourceHandler: Seq count provider bit width %d not allowed\n",
|
|
||||||
sourceParams.seqCountProvider.bitWidth());
|
|
||||||
#endif
|
|
||||||
// Yeah, what am I supposed to do here? Can't throw an exception in the FSFW..
|
|
||||||
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
|
|
||||||
}
|
|
||||||
transactionParams.pduConf.seqNum.setValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
|
||||||
ReturnValue_t result;
|
|
||||||
if (step == TransactionStep::IDLE) {
|
|
||||||
step = TransactionStep::TRANSACTION_START;
|
|
||||||
}
|
|
||||||
if (step == TransactionStep::TRANSACTION_START) {
|
|
||||||
sourceParams.user.transactionIndication(transactionParams.id);
|
|
||||||
result = checksumGeneration();
|
|
||||||
if (result != OK) {
|
|
||||||
addError(result);
|
|
||||||
}
|
|
||||||
step = TransactionStep::SENDING_METADATA;
|
|
||||||
}
|
|
||||||
if (step == TransactionStep::SENDING_METADATA) {
|
|
||||||
result = prepareAndSendMetadataPdu();
|
|
||||||
if (result != OK) {
|
|
||||||
addError(result);
|
|
||||||
}
|
|
||||||
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
|
||||||
return fsmResult;
|
|
||||||
}
|
|
||||||
if (step == TransactionStep::SENDING_FILE_DATA) {
|
|
||||||
bool noFdPdu = false;
|
|
||||||
result = prepareAndSendNextFileDataPdu(noFdPdu);
|
|
||||||
if (result == OK and !noFdPdu) {
|
|
||||||
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
|
||||||
return fsmResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (step == TransactionStep::SENDING_EOF) {
|
|
||||||
result = prepareAndSendEofPdu();
|
|
||||||
if (result != OK) {
|
|
||||||
addError(result);
|
|
||||||
}
|
|
||||||
if (sourceParams.cfg.indicCfg.eofSentIndicRequired) {
|
|
||||||
sourceParams.user.eofSentIndication(transactionParams.id);
|
|
||||||
}
|
|
||||||
if (transactionParams.closureRequested) {
|
|
||||||
step = TransactionStep::WAIT_FOR_FINISH;
|
|
||||||
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
||||||
} else {
|
|
||||||
step = TransactionStep::NOTICE_OF_COMPLETION;
|
|
||||||
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
|
||||||
}
|
|
||||||
return fsmResult;
|
|
||||||
}
|
|
||||||
if (step == TransactionStep::WAIT_FOR_FINISH) {
|
|
||||||
// TODO: In case this is a request with closure, wait for finish.
|
|
||||||
// Done, issue notice of completion
|
|
||||||
step = TransactionStep::NOTICE_OF_COMPLETION;
|
|
||||||
}
|
|
||||||
if (step == TransactionStep::NOTICE_OF_COMPLETION) {
|
|
||||||
noticeOfCompletion();
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
return fsmResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() {
|
|
||||||
fsmResult.packetsSent = 0;
|
|
||||||
fsmResult.errors = 0;
|
|
||||||
fsmResult.callStatus = CallStatus::DONE;
|
|
||||||
if (state == cfdp::CfdpState::IDLE) {
|
|
||||||
return fsmResult;
|
|
||||||
}
|
|
||||||
if (state == cfdp::CfdpState::BUSY_CLASS_1_NACKED) {
|
|
||||||
return fsmNacked();
|
|
||||||
}
|
|
||||||
return fsmResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
|
|
||||||
if (transactionParams.fileSize.value() == 0) {
|
|
||||||
// NULL checksum for empty file.
|
|
||||||
transactionParams.crc = 0;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
std::array<uint8_t, 1024> buf{};
|
|
||||||
etl::crc32 crcCalc;
|
|
||||||
uint64_t currentOffset = 0;
|
|
||||||
FileOpParams params(transactionParams.sourceName.data(), transactionParams.fileSize.value());
|
|
||||||
while (currentOffset < transactionParams.fileSize.value()) {
|
|
||||||
uint64_t readLen;
|
|
||||||
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
|
|
||||||
readLen = transactionParams.fileSize.value() - currentOffset;
|
|
||||||
} else {
|
|
||||||
readLen = buf.size();
|
|
||||||
}
|
|
||||||
if (readLen > 0) {
|
|
||||||
params.offset = currentOffset;
|
|
||||||
params.size = readLen;
|
|
||||||
auto result = sourceParams.user.vfs.readFromFile(params, buf.data(), buf.size());
|
|
||||||
if (result != OK) {
|
|
||||||
addError(result);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
crcCalc.add(buf.begin(), buf.begin() + readLen);
|
|
||||||
}
|
|
||||||
currentOffset += readLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionParams.crc = crcCalc.value();
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg) {
|
|
||||||
if (state != CfdpState::IDLE) {
|
|
||||||
return SOURCE_TRANSACTION_PENDING;
|
|
||||||
}
|
|
||||||
if (cfg.remoteId != putRequest.getDestId()) {
|
|
||||||
return WRONG_REMOTE_CFG_ENTITY_ID;
|
|
||||||
}
|
|
||||||
if (putRequest.getSourceName().getValueLen() == 0) {
|
|
||||||
return SOURCE_NAME_EMPTY;
|
|
||||||
}
|
|
||||||
if (putRequest.getDestName().getValueLen() == 0) {
|
|
||||||
return DEST_NAME_EMPTY;
|
|
||||||
}
|
|
||||||
const char* srcNamePtr = putRequest.getSourceName().getCString(transactionParams.sourceNameSize);
|
|
||||||
const char* destNamePtr = putRequest.getDestName().getCString(transactionParams.destNameSize);
|
|
||||||
std::strncpy(transactionParams.sourceName.data(), srcNamePtr, transactionParams.sourceNameSize);
|
|
||||||
std::strncpy(transactionParams.destName.data(), destNamePtr, transactionParams.destNameSize);
|
|
||||||
// Add 0 termination. The source and dest name size can not be larger than UINT8_MAX, so this
|
|
||||||
// operation is safe.
|
|
||||||
transactionParams.sourceName[transactionParams.sourceNameSize] = '\0';
|
|
||||||
transactionParams.destName[transactionParams.destNameSize] = '\0';
|
|
||||||
FilesystemParams params(transactionParams.sourceName.data());
|
|
||||||
if (!sourceParams.user.vfs.fileExists(params)) {
|
|
||||||
return FILE_DOES_NOT_EXIST;
|
|
||||||
}
|
|
||||||
if (cfg.maxFileSegmentLen > fileBuf.size() or cfg.maxFileSegmentLen == 0) {
|
|
||||||
return FILE_SEGMENT_LEN_INVALID;
|
|
||||||
}
|
|
||||||
// If transmission mode is not set, use default transmission mode for the remote entity.
|
|
||||||
if (not putRequest.getTransmissionMode(transactionParams.pduConf.mode)) {
|
|
||||||
transactionParams.pduConf.mode = cfg.defaultTransmissionMode;
|
|
||||||
}
|
|
||||||
// If closure request field is not set, use default option for the remote entity.
|
|
||||||
if (not putRequest.getClosureRequested(transactionParams.closureRequested)) {
|
|
||||||
transactionParams.closureRequested = cfg.closureRequested;
|
|
||||||
}
|
|
||||||
const EntityId& destId = putRequest.getDestId();
|
|
||||||
// The width of the source and destination ID must be the same. Use the larger ID value to
|
|
||||||
// ensure the width is large enough for both IDs
|
|
||||||
if (destId.getWidth() > transactionParams.pduConf.sourceId.getWidth()) {
|
|
||||||
transactionParams.pduConf.destId = destId;
|
|
||||||
transactionParams.pduConf.sourceId.setWidth(destId.getWidth());
|
|
||||||
} else {
|
|
||||||
transactionParams.pduConf.destId.setValueAndWidth(transactionParams.pduConf.sourceId.getWidth(),
|
|
||||||
destId.getValue());
|
|
||||||
}
|
|
||||||
// Only used for PDU forwarding, file is sent to file receiver regularly here.
|
|
||||||
transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
|
|
||||||
transactionParams.pduConf.seqNum.setValue(sourceParams.seqCountProvider.getAndIncrement());
|
|
||||||
transactionParams.id.seqNum = transactionParams.pduConf.seqNum;
|
|
||||||
|
|
||||||
if (transactionParams.pduConf.mode == TransmissionMode::ACKNOWLEDGED) {
|
|
||||||
state = cfdp::CfdpState::BUSY_CLASS_2_ACKED;
|
|
||||||
} else if (transactionParams.pduConf.mode == TransmissionMode::UNACKNOWLEDGED) {
|
|
||||||
state = cfdp::CfdpState::BUSY_CLASS_1_NACKED;
|
|
||||||
}
|
|
||||||
step = TransactionStep::IDLE;
|
|
||||||
uint64_t fileSize = 0;
|
|
||||||
sourceParams.user.vfs.getFileSize(params, fileSize);
|
|
||||||
transactionParams.pduConf.largeFile = false;
|
|
||||||
if (fileSize > UINT32_MAX) {
|
|
||||||
transactionParams.pduConf.largeFile = true;
|
|
||||||
}
|
|
||||||
if (fileSize == 0) {
|
|
||||||
transactionParams.checksumType = ChecksumType::NULL_CHECKSUM;
|
|
||||||
} else {
|
|
||||||
transactionParams.checksumType = ChecksumType::CRC_32;
|
|
||||||
}
|
|
||||||
transactionParams.fileSize.setFileSize(fileSize, transactionParams.pduConf.largeFile);
|
|
||||||
transactionParams.progress = 0;
|
|
||||||
transactionParams.remoteCfg = cfg;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::prepareAndSendMetadataPdu() {
|
|
||||||
cfdp::StringLv sourceName(transactionParams.sourceName.data(), transactionParams.sourceNameSize);
|
|
||||||
cfdp::StringLv destName(transactionParams.destName.data(), transactionParams.destNameSize);
|
|
||||||
auto metadataInfo =
|
|
||||||
MetadataGenericInfo(transactionParams.closureRequested, transactionParams.checksumType,
|
|
||||||
transactionParams.fileSize);
|
|
||||||
auto metadataPdu =
|
|
||||||
MetadataPduCreator(transactionParams.pduConf, metadataInfo, sourceName, destName, nullptr, 0);
|
|
||||||
ReturnValue_t result = sendGenericPdu(metadataPdu);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// Advance FSM if everything works
|
|
||||||
step = TransactionStep::SENDING_FILE_DATA;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu(bool& noFileDataPdu) {
|
|
||||||
cfdp::Fss offset(transactionParams.progress);
|
|
||||||
uint64_t readLen;
|
|
||||||
uint64_t fileSize = transactionParams.fileSize.value();
|
|
||||||
noFileDataPdu = false;
|
|
||||||
if (fileSize == 0) {
|
|
||||||
// We are done, no need to send file data PDUs for an empty file.
|
|
||||||
step = TransactionStep::SENDING_EOF;
|
|
||||||
noFileDataPdu = true;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
if (fileSize < transactionParams.remoteCfg.maxFileSegmentLen) {
|
|
||||||
readLen = transactionParams.fileSize.value();
|
|
||||||
} else {
|
|
||||||
if (transactionParams.progress + transactionParams.remoteCfg.maxFileSegmentLen > fileSize) {
|
|
||||||
readLen = fileSize - transactionParams.progress;
|
|
||||||
} else {
|
|
||||||
readLen = transactionParams.remoteCfg.maxFileSegmentLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FileOpParams fileParams(transactionParams.sourceName.data(), readLen);
|
|
||||||
fileParams.offset = transactionParams.progress;
|
|
||||||
ReturnValue_t result =
|
|
||||||
sourceParams.user.vfs.readFromFile(fileParams, fileBuf.data(), fileBuf.size());
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
addError(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
auto fileDataInfo = FileDataInfo(offset, fileBuf.data(), readLen);
|
|
||||||
auto fileDataPdu = FileDataCreator(transactionParams.pduConf, fileDataInfo);
|
|
||||||
result = sendGenericPdu(fileDataPdu);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
transactionParams.progress += readLen;
|
|
||||||
if (transactionParams.progress >= fileSize) {
|
|
||||||
// Advance FSM after all file data PDUs were sent.
|
|
||||||
step = TransactionStep::SENDING_EOF;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() {
|
|
||||||
auto eofInfo =
|
|
||||||
EofInfo(ConditionCode::NO_ERROR, transactionParams.crc, transactionParams.fileSize);
|
|
||||||
auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo);
|
|
||||||
ReturnValue_t result = sendGenericPdu(eofPdu);
|
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::initialize() {
|
|
||||||
if (fsfwParams.tmStore == nullptr) {
|
|
||||||
fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
|
|
||||||
if (fsfwParams.tmStore == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsfwParams.tcStore == nullptr) {
|
|
||||||
fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
|
||||||
if (fsfwParams.tcStore == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsfwParams.msgQueue == nullptr) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) {
|
|
||||||
uint8_t* dataPtr;
|
|
||||||
store_address_t storeId;
|
|
||||||
ReturnValue_t result =
|
|
||||||
fsfwParams.tmStore->getFreeElement(&storeId, pdu.getSerializedSize(), &dataPtr);
|
|
||||||
if (result != OK) {
|
|
||||||
addError(result);
|
|
||||||
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
||||||
if (result == StorageManagerIF::DATA_STORAGE_FULL) {
|
|
||||||
return TM_STORE_FULL;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
size_t serializedLen = 0;
|
|
||||||
result = pdu.serializeBe(dataPtr, serializedLen, pdu.getSerializedSize());
|
|
||||||
if (result != OK) {
|
|
||||||
addError(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
TmTcMessage tmMsg(storeId);
|
|
||||||
result =
|
|
||||||
fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg);
|
|
||||||
if (result != OK) {
|
|
||||||
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
||||||
}
|
|
||||||
if (result == MessageQueueIF::FULL) {
|
|
||||||
return TARGET_MSG_QUEUE_FULL;
|
|
||||||
} else if (result == OK) {
|
|
||||||
fsmResult.packetsSent += 1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::noticeOfCompletion() {
|
|
||||||
if (sourceParams.cfg.indicCfg.transactionFinishedIndicRequired) {
|
|
||||||
cfdp::TransactionFinishedParams params(transactionParams.id, ConditionCode::NO_ERROR,
|
|
||||||
FileDeliveryCode::DATA_COMPLETE,
|
|
||||||
FileDeliveryStatus::RETAINED_IN_FILESTORE);
|
|
||||||
sourceParams.user.transactionFinishedIndication(params);
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::reset() {
|
|
||||||
step = TransactionStep::IDLE;
|
|
||||||
state = cfdp::CfdpState::IDLE;
|
|
||||||
fsmResult.callStatus = CallStatus::DONE;
|
|
||||||
transactionParams.reset();
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
cfdp::CfdpState cfdp::SourceHandler::getState() const { return state; }
|
|
||||||
|
|
||||||
cfdp::SourceHandler::TransactionStep cfdp::SourceHandler::getStep() const { return step; }
|
|
||||||
|
|
||||||
void cfdp::SourceHandler::addError(ReturnValue_t error) {
|
|
||||||
if (fsmResult.errors < fsmResult.errorCodes.size()) {
|
|
||||||
fsmResult.errorCodes[fsmResult.errors] = error;
|
|
||||||
fsmResult.errors++;
|
|
||||||
fsmResult.result = error;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
|
|
||||||
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "UserBase.h"
|
|
||||||
#include "defs.h"
|
|
||||||
#include "fsfw/cfdp/Fss.h"
|
|
||||||
#include "fsfw/cfdp/handler/PutRequest.h"
|
|
||||||
#include "fsfw/cfdp/handler/mib.h"
|
|
||||||
#include "fsfw/events/EventReportingProxyIF.h"
|
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
|
||||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
|
||||||
#include "fsfw/util/ProvidesSeqCountIF.h"
|
|
||||||
|
|
||||||
namespace cfdp {
|
|
||||||
|
|
||||||
struct SourceHandlerParams {
|
|
||||||
SourceHandlerParams(LocalEntityCfg cfg, UserBase& user, ProvidesSeqCountIF& seqCountProvider)
|
|
||||||
: cfg(std::move(cfg)), user(user), seqCountProvider(seqCountProvider) {}
|
|
||||||
|
|
||||||
LocalEntityCfg cfg;
|
|
||||||
UserBase& user;
|
|
||||||
ProvidesSeqCountIF& seqCountProvider;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SourceHandler {
|
|
||||||
public:
|
|
||||||
enum class TransactionStep : uint8_t {
|
|
||||||
IDLE = 0,
|
|
||||||
TRANSACTION_START = 1,
|
|
||||||
SENDING_METADATA = 3,
|
|
||||||
SENDING_FILE_DATA = 4,
|
|
||||||
SENDING_EOF = 5,
|
|
||||||
WAIT_FOR_ACK = 6,
|
|
||||||
WAIT_FOR_FINISH = 7,
|
|
||||||
NOTICE_OF_COMPLETION = 8
|
|
||||||
};
|
|
||||||
struct FsmResult {
|
|
||||||
public:
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
||||||
CfdpState state = CfdpState::IDLE;
|
|
||||||
uint32_t packetsSent = 0;
|
|
||||||
uint8_t errors = 0;
|
|
||||||
std::array<ReturnValue_t, 3> errorCodes = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams);
|
|
||||||
|
|
||||||
[[nodiscard]] CfdpState getState() const;
|
|
||||||
[[nodiscard]] TransactionStep getStep() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass a put request to the source handler, which might initiate a CFDP transaction and start
|
|
||||||
* the state machine
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ReturnValue_t transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg);
|
|
||||||
const FsmResult& stateMachine();
|
|
||||||
|
|
||||||
ReturnValue_t initialize();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct TransactionParams {
|
|
||||||
uint32_t crc{};
|
|
||||||
std::array<char, UINT8_MAX + 1> sourceName{};
|
|
||||||
size_t sourceNameSize = 0;
|
|
||||||
std::array<char, UINT8_MAX + 1> destName{};
|
|
||||||
size_t destNameSize = 0;
|
|
||||||
cfdp::Fss fileSize;
|
|
||||||
size_t progress = 0;
|
|
||||||
bool closureRequested = false;
|
|
||||||
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
|
|
||||||
RemoteEntityCfg remoteCfg;
|
|
||||||
PduConfig pduConf;
|
|
||||||
cfdp::TransactionId id{};
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
sourceNameSize = 0;
|
|
||||||
destNameSize = 0;
|
|
||||||
fileSize.setFileSize(0, false);
|
|
||||||
progress = 0;
|
|
||||||
closureRequested = false;
|
|
||||||
}
|
|
||||||
} transactionParams;
|
|
||||||
|
|
||||||
cfdp::CfdpState state = cfdp::CfdpState::IDLE;
|
|
||||||
TransactionStep step = TransactionStep::IDLE;
|
|
||||||
std::array<uint8_t, 4096> fileBuf{};
|
|
||||||
SourceHandlerParams sourceParams;
|
|
||||||
cfdp::FsfwParams fsfwParams;
|
|
||||||
FsmResult fsmResult;
|
|
||||||
|
|
||||||
FsmResult& fsmNacked();
|
|
||||||
ReturnValue_t checksumGeneration();
|
|
||||||
ReturnValue_t prepareAndSendMetadataPdu();
|
|
||||||
ReturnValue_t prepareAndSendNextFileDataPdu(bool& noFileDataPdu);
|
|
||||||
ReturnValue_t prepareAndSendEofPdu();
|
|
||||||
ReturnValue_t noticeOfCompletion();
|
|
||||||
ReturnValue_t reset();
|
|
||||||
|
|
||||||
[[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu);
|
|
||||||
void addError(ReturnValue_t error);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cfdp
|
|
||||||
|
|
||||||
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H
|
|
@ -6,7 +6,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "StatusReportIF.h"
|
#include "StatusReportIF.h"
|
||||||
#include "fsfw/cfdp/Fss.h"
|
|
||||||
#include "fsfw/cfdp/VarLenFields.h"
|
#include "fsfw/cfdp/VarLenFields.h"
|
||||||
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
|
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
|
||||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
||||||
@ -28,14 +27,14 @@ struct TransactionFinishedParams {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MetadataRecvdParams {
|
struct MetadataRecvdParams {
|
||||||
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId, Fss fileSize)
|
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId)
|
||||||
: id(id), sourceId(sourceId), fileSize(std::move(fileSize)) {}
|
: id(id), sourceId(sourceId) {}
|
||||||
const TransactionId& id;
|
const TransactionId& id;
|
||||||
const EntityId& sourceId;
|
const EntityId& sourceId;
|
||||||
Fss fileSize{};
|
uint64_t fileSize = 0;
|
||||||
const char* sourceFileName = "";
|
const char* sourceFileName = "";
|
||||||
const char* destFileName = "";
|
const char* destFileName = "";
|
||||||
size_t numberOfMsgsToUser = 0;
|
size_t msgsToUserLen = 0;
|
||||||
const MessageToUserTlv* msgsToUserArray = nullptr;
|
const MessageToUserTlv* msgsToUserArray = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,10 +65,10 @@ struct FileSegmentRecvdParams {
|
|||||||
*/
|
*/
|
||||||
class UserBase {
|
class UserBase {
|
||||||
friend class DestHandler;
|
friend class DestHandler;
|
||||||
friend class SourceHandler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit UserBase(HasFileSystemIF& vfs);
|
explicit UserBase(HasFileSystemIF& vfs);
|
||||||
|
virtual ~UserBase() = default;
|
||||||
|
|
||||||
virtual void transactionIndication(const TransactionId& id) = 0;
|
virtual void transactionIndication(const TransactionId& id) = 0;
|
||||||
virtual void eofSentIndication(const TransactionId& id) = 0;
|
virtual void eofSentIndication(const TransactionId& id) = 0;
|
||||||
|
@ -1,76 +1,9 @@
|
|||||||
#ifndef FSFW_CFDP_HANDLER_DEFS_H
|
#ifndef FSFW_CFDP_HANDLER_DEFS_H
|
||||||
#define FSFW_CFDP_HANDLER_DEFS_H
|
#define FSFW_CFDP_HANDLER_DEFS_H
|
||||||
|
|
||||||
#include <etl/list.h>
|
|
||||||
|
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
|
||||||
#include "fsfw/storagemanager/storeAddress.h"
|
|
||||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
|
||||||
|
|
||||||
namespace cfdp {
|
namespace cfdp {
|
||||||
|
|
||||||
enum class CfdpState { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
|
enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
|
||||||
|
|
||||||
static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP;
|
}
|
||||||
static constexpr uint8_t CID = CLASS_ID::CFDP_HANDLER;
|
|
||||||
|
|
||||||
struct PacketInfo {
|
|
||||||
PacketInfo(PduType type, store_address_t storeId,
|
|
||||||
std::optional<FileDirective> directive = std::nullopt)
|
|
||||||
: pduType(type), directiveType(directive), storeId(storeId) {}
|
|
||||||
|
|
||||||
PduType pduType = PduType::FILE_DATA;
|
|
||||||
std::optional<FileDirective> directiveType = FileDirective::INVALID_DIRECTIVE;
|
|
||||||
store_address_t storeId = store_address_t::invalid();
|
|
||||||
PacketInfo() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FsfwParams {
|
|
||||||
FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
|
|
||||||
EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore,
|
|
||||||
StorageManagerIF& tmStore)
|
|
||||||
: FsfwParams(packetDest, msgQueue, eventReporter) {
|
|
||||||
this->tcStore = &tcStore;
|
|
||||||
this->tmStore = &tmStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
|
|
||||||
EventReportingProxyIF* eventReporter)
|
|
||||||
: packetDest(packetDest), msgQueue(msgQueue), eventReporter(eventReporter) {}
|
|
||||||
AcceptsTelemetryIF& packetDest;
|
|
||||||
MessageQueueIF* msgQueue;
|
|
||||||
EventReportingProxyIF* eventReporter = nullptr;
|
|
||||||
StorageManagerIF* tcStore = nullptr;
|
|
||||||
StorageManagerIF* tmStore = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t SIZE>
|
|
||||||
using PacketInfoList = etl::list<PacketInfo, SIZE>;
|
|
||||||
using PacketInfoListBase = etl::ilist<PacketInfo>;
|
|
||||||
|
|
||||||
enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
|
|
||||||
|
|
||||||
namespace events {
|
|
||||||
|
|
||||||
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);
|
|
||||||
static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW);
|
|
||||||
static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
|
|
||||||
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
|
|
||||||
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
|
|
||||||
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
|
|
||||||
//! [EXPORT] : [COMMENT] CFDP request handling failed. P2: Returncode.
|
|
||||||
static constexpr Event HANDLING_CFDP_REQUEST_FAILED = event::makeEvent(SSID, 5, severity::LOW);
|
|
||||||
|
|
||||||
} // namespace events
|
|
||||||
|
|
||||||
static constexpr ReturnValue_t SOURCE_TRANSACTION_PENDING = returnvalue::makeCode(CID, 0);
|
|
||||||
static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = returnvalue::makeCode(CID, 1);
|
|
||||||
static constexpr ReturnValue_t FILE_SEGMENT_LEN_INVALID = returnvalue::makeCode(CID, 2);
|
|
||||||
static constexpr ReturnValue_t SOURCE_NAME_EMPTY = returnvalue::makeCode(CID, 3);
|
|
||||||
static constexpr ReturnValue_t DEST_NAME_EMPTY = returnvalue::makeCode(CID, 4);
|
|
||||||
static constexpr ReturnValue_t WRONG_REMOTE_CFG_ENTITY_ID = returnvalue::makeCode(CID, 5);
|
|
||||||
static constexpr ReturnValue_t TARGET_MSG_QUEUE_FULL = returnvalue::makeCode(CID, 6);
|
|
||||||
static constexpr ReturnValue_t TM_STORE_FULL = returnvalue::makeCode(CID, 7);
|
|
||||||
|
|
||||||
} // namespace cfdp
|
|
||||||
#endif // FSFW_CFDP_HANDLER_DEFS_H
|
#endif // FSFW_CFDP_HANDLER_DEFS_H
|
||||||
|
@ -27,15 +27,14 @@ struct LocalEntityCfg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RemoteEntityCfg {
|
struct RemoteEntityCfg {
|
||||||
RemoteEntityCfg() = default;
|
|
||||||
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
|
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
|
||||||
EntityId remoteId;
|
EntityId remoteId;
|
||||||
size_t maxFileSegmentLen = 1024;
|
size_t maxFileSegmentLen = 2048;
|
||||||
bool closureRequested = false;
|
bool closureRequested = false;
|
||||||
bool crcOnTransmission = false;
|
bool crcOnTransmission = false;
|
||||||
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
|
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
|
||||||
ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM;
|
ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM;
|
||||||
uint8_t version = CFDP_VERSION_2;
|
const uint8_t version = CFDP_VERSION_2;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cfdp
|
} // namespace cfdp
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
const char* COND_CODE_STRINGS[14] = {"Unknown",
|
static const char* COND_CODE_STRINGS[14] = {"Unknown",
|
||||||
"No Error",
|
"No Error",
|
||||||
"Positive ACK Limit Reached",
|
"Positive ACK Limit Reached",
|
||||||
"Keep Alive Limit Reached",
|
"Keep Alive Limit Reached",
|
||||||
|
@ -17,7 +17,7 @@ target_sources(
|
|||||||
FinishedInfo.cpp
|
FinishedInfo.cpp
|
||||||
FinishedPduCreator.cpp
|
FinishedPduCreator.cpp
|
||||||
FinishedPduReader.cpp
|
FinishedPduReader.cpp
|
||||||
MetadataGenericInfo.cpp
|
MetadataInfo.cpp
|
||||||
MetadataPduCreator.cpp
|
MetadataPduCreator.cpp
|
||||||
MetadataPduReader.cpp
|
MetadataPduReader.cpp
|
||||||
KeepAlivePduCreator.cpp
|
KeepAlivePduCreator.cpp
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
#include "EofInfo.h"
|
#include "EofInfo.h"
|
||||||
|
|
||||||
#include <utility>
|
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
|
||||||
|
|
||||||
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
|
|
||||||
EntityIdTlv* faultLoc)
|
EntityIdTlv* faultLoc)
|
||||||
: conditionCode(conditionCode),
|
: conditionCode(conditionCode), checksum(checksum), fileSize(fileSize), faultLoc(faultLoc) {}
|
||||||
checksum(checksum),
|
|
||||||
fileSize(std::move(fileSize)),
|
|
||||||
faultLoc(faultLoc) {}
|
|
||||||
|
|
||||||
EofInfo::EofInfo(EntityIdTlv* faultLoc)
|
EofInfo::EofInfo(EntityIdTlv* faultLoc)
|
||||||
: conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD),
|
: conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD),
|
||||||
@ -21,15 +16,15 @@ cfdp::ConditionCode EofInfo::getConditionCode() const { return conditionCode; }
|
|||||||
|
|
||||||
EntityIdTlv* EofInfo::getFaultLoc() const { return faultLoc; }
|
EntityIdTlv* EofInfo::getFaultLoc() const { return faultLoc; }
|
||||||
|
|
||||||
cfdp::Fss& EofInfo::getFileSize() { return fileSize; }
|
cfdp::FileSize& EofInfo::getFileSize() { return fileSize; }
|
||||||
|
|
||||||
void EofInfo::setChecksum(uint32_t checksum_) { this->checksum = checksum_; }
|
void EofInfo::setChecksum(uint32_t checksum) { this->checksum = checksum; }
|
||||||
|
|
||||||
void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode_) {
|
void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
|
||||||
this->conditionCode = conditionCode_;
|
this->conditionCode = conditionCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EofInfo::setFaultLoc(EntityIdTlv* faultLoc_) { this->faultLoc = faultLoc_; }
|
void EofInfo::setFaultLoc(EntityIdTlv* faultLoc) { this->faultLoc = faultLoc; }
|
||||||
|
|
||||||
size_t EofInfo::getSerializedSize(bool fssLarge) {
|
size_t EofInfo::getSerializedSize(bool fssLarge) {
|
||||||
// Condition code + spare + 4 byte checksum
|
// Condition code + spare + 4 byte checksum
|
||||||
@ -47,6 +42,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t EofInfo::setFileSize(size_t fileSize_, bool isLarge) {
|
ReturnValue_t EofInfo::setFileSize(uint64_t fileSize, bool isLarge) {
|
||||||
return this->fileSize.setFileSize(fileSize_, isLarge);
|
return this->fileSize.setFileSize(fileSize, isLarge);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
|
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
|
||||||
#define FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
|
#define FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
|
||||||
|
|
||||||
#include "../Fss.h"
|
#include "../FileSize.h"
|
||||||
#include "../definitions.h"
|
#include "../definitions.h"
|
||||||
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
|
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
|
||||||
|
|
||||||
struct EofInfo {
|
struct EofInfo {
|
||||||
public:
|
public:
|
||||||
explicit EofInfo(EntityIdTlv* faultLoc = nullptr);
|
explicit EofInfo(EntityIdTlv* faultLoc = nullptr);
|
||||||
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
|
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
|
||||||
EntityIdTlv* faultLoc = nullptr);
|
EntityIdTlv* faultLoc = nullptr);
|
||||||
|
|
||||||
size_t getSerializedSize(bool fssLarge = false);
|
size_t getSerializedSize(bool fssLarge = false);
|
||||||
@ -17,16 +17,16 @@ struct EofInfo {
|
|||||||
[[nodiscard]] cfdp::ConditionCode getConditionCode() const;
|
[[nodiscard]] cfdp::ConditionCode getConditionCode() const;
|
||||||
|
|
||||||
[[nodiscard]] EntityIdTlv* getFaultLoc() const;
|
[[nodiscard]] EntityIdTlv* getFaultLoc() const;
|
||||||
cfdp::Fss& getFileSize();
|
cfdp::FileSize& getFileSize();
|
||||||
void setChecksum(uint32_t checksum);
|
void setChecksum(uint32_t checksum);
|
||||||
void setConditionCode(cfdp::ConditionCode conditionCode);
|
void setConditionCode(cfdp::ConditionCode conditionCode);
|
||||||
void setFaultLoc(EntityIdTlv* faultLoc);
|
void setFaultLoc(EntityIdTlv* faultLoc);
|
||||||
ReturnValue_t setFileSize(size_t size, bool isLarge);
|
ReturnValue_t setFileSize(uint64_t size, bool isLarge);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cfdp::ConditionCode conditionCode;
|
cfdp::ConditionCode conditionCode;
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
cfdp::Fss fileSize;
|
cfdp::FileSize fileSize;
|
||||||
EntityIdTlv* faultLoc = nullptr;
|
EntityIdTlv* faultLoc = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
|
|||||||
*buffer += segmentMetadataLen;
|
*buffer += segmentMetadataLen;
|
||||||
*size += segmentMetadataLen;
|
*size += segmentMetadataLen;
|
||||||
}
|
}
|
||||||
cfdp::Fss& offset = info.getOffset();
|
cfdp::FileSize& offset = info.getOffset();
|
||||||
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "FileDataInfo.h"
|
#include "FileDataInfo.h"
|
||||||
|
|
||||||
#include <utility>
|
FileDataInfo::FileDataInfo(cfdp::FileSize &offset, const uint8_t *fileData, size_t fileSize)
|
||||||
|
: offset(offset), fileData(fileData), fileSize(fileSize) {}
|
||||||
|
|
||||||
FileDataInfo::FileDataInfo(cfdp::Fss offset, const uint8_t *fileData, size_t fileSize)
|
FileDataInfo::FileDataInfo(cfdp::FileSize &offset) : offset(offset) {}
|
||||||
: offset(std::move(offset)), fileData(fileData), fileSize(fileSize) {}
|
|
||||||
|
|
||||||
void FileDataInfo::setSegmentMetadataFlag(bool enable) {
|
void FileDataInfo::setSegmentMetadataFlag(bool enable) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
@ -71,7 +71,7 @@ const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) {
|
|||||||
return segmentMetadata;
|
return segmentMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::Fss &FileDataInfo::getOffset() { return offset; }
|
cfdp::FileSize &FileDataInfo::getOffset() { return offset; }
|
||||||
|
|
||||||
void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) {
|
void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) {
|
||||||
this->recContState = recContState;
|
this->recContState = recContState;
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
|
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
|
||||||
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
|
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
|
||||||
|
|
||||||
#include <fsfw/cfdp/Fss.h>
|
#include <fsfw/cfdp/FileSize.h>
|
||||||
#include <fsfw/cfdp/definitions.h>
|
#include <fsfw/cfdp/definitions.h>
|
||||||
|
|
||||||
class FileDataInfo {
|
class FileDataInfo {
|
||||||
public:
|
public:
|
||||||
FileDataInfo() = default;
|
explicit FileDataInfo(cfdp::FileSize& offset);
|
||||||
FileDataInfo(cfdp::Fss offset, const uint8_t* fileData, size_t fileSize);
|
FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
|
||||||
|
|
||||||
[[nodiscard]] size_t getSerializedSize(bool largeFile = false) const;
|
[[nodiscard]] size_t getSerializedSize(bool largeFile = false) const;
|
||||||
|
|
||||||
cfdp::Fss& getOffset();
|
cfdp::FileSize& getOffset();
|
||||||
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
|
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
|
||||||
void setFileData(const uint8_t* fileData, size_t fileSize);
|
void setFileData(const uint8_t* fileData, size_t fileSize);
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ class FileDataInfo {
|
|||||||
private:
|
private:
|
||||||
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
|
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
|
||||||
cfdp::SegmentationControl segCtrl = cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION;
|
cfdp::SegmentationControl segCtrl = cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION;
|
||||||
cfdp::Fss offset;
|
cfdp::FileSize& offset;
|
||||||
const uint8_t* fileData = nullptr;
|
const uint8_t* fileData = nullptr;
|
||||||
size_t fileSize = 0;
|
size_t fileSize = 0;
|
||||||
cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END;
|
cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END;
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
#include "FinishedPduReader.h"
|
#include "FinishedPduReader.h"
|
||||||
|
|
||||||
|
// Thanks, windows
|
||||||
|
#ifdef NO_ERROR
|
||||||
|
#undef NO_ERROR
|
||||||
|
#endif
|
||||||
|
|
||||||
FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info)
|
FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info)
|
||||||
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}
|
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
|||||||
*buffer += 1;
|
*buffer += 1;
|
||||||
**buffer = pduDataFieldLen & 0x00ff;
|
**buffer = pduDataFieldLen & 0x00ff;
|
||||||
*buffer += 1;
|
*buffer += 1;
|
||||||
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
|
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
|
||||||
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
|
pduConf.seqNum.getWidth();
|
||||||
*buffer += 1;
|
*buffer += 1;
|
||||||
*size += 4;
|
*size += 4;
|
||||||
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
|
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
|
||||||
|
@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
|
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
|
||||||
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
|
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
|
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
|
||||||
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
|
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
|
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
|
||||||
@ -103,11 +103,11 @@ void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
|
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
|
||||||
void *sourcePtr) {
|
void *sourcePtr) const {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||||
auto *fieldTyped = static_cast<uint8_t *>(sourcePtr);
|
auto *fieldTyped = static_cast<uint8_t *>(sourcePtr);
|
||||||
field->setValueAndWidth(width, *fieldTyped);
|
field->setValue(width, *fieldTyped);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::TWO_BYTES): {
|
case (cfdp::WidthInBytes::TWO_BYTES): {
|
||||||
@ -115,7 +115,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
|
|||||||
size_t deserSize = 0;
|
size_t deserSize = 0;
|
||||||
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
||||||
SerializeIF::Endianness::NETWORK);
|
SerializeIF::Endianness::NETWORK);
|
||||||
field->setValueAndWidth(width, fieldTyped);
|
field->setValue(width, fieldTyped);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
@ -123,15 +123,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
|
|||||||
size_t deserSize = 0;
|
size_t deserSize = 0;
|
||||||
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
||||||
SerializeIF::Endianness::NETWORK);
|
SerializeIF::Endianness::NETWORK);
|
||||||
field->setValueAndWidth(width, fieldTyped);
|
field->setValue(width, fieldTyped);
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
|
||||||
uint64_t fieldTyped = 0;
|
|
||||||
size_t deserSize = 0;
|
|
||||||
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
|
||||||
SerializeIF::Endianness::NETWORK);
|
|
||||||
field->setValueAndWidth(width, fieldTyped);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "KeepAlivePduCreator.h"
|
#include "KeepAlivePduCreator.h"
|
||||||
|
|
||||||
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::Fss &progress)
|
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::FileSize &progress)
|
||||||
: FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) {
|
: FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) {
|
||||||
updateDirectiveFieldLen();
|
updateDirectiveFieldLen();
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
|
#ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
|
||||||
#define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
|
#define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
|
||||||
|
|
||||||
#include "fsfw/cfdp/Fss.h"
|
#include "fsfw/cfdp/FileSize.h"
|
||||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||||
|
|
||||||
class KeepAlivePduCreator : public FileDirectiveCreator {
|
class KeepAlivePduCreator : public FileDirectiveCreator {
|
||||||
public:
|
public:
|
||||||
KeepAlivePduCreator(PduConfig& conf, cfdp::Fss& progress);
|
KeepAlivePduCreator(PduConfig& conf, cfdp::FileSize& progress);
|
||||||
|
|
||||||
void updateDirectiveFieldLen();
|
void updateDirectiveFieldLen();
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ class KeepAlivePduCreator : public FileDirectiveCreator {
|
|||||||
Endianness streamEndianness) const override;
|
Endianness streamEndianness) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cfdp::Fss& progress;
|
cfdp::FileSize& progress;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */
|
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "KeepAlivePduReader.h"
|
#include "KeepAlivePduReader.h"
|
||||||
|
|
||||||
KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress)
|
KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize,
|
||||||
|
cfdp::FileSize& progress)
|
||||||
: FileDirectiveReader(pduBuf, maxSize), progress(progress) {}
|
: FileDirectiveReader(pduBuf, maxSize), progress(progress) {}
|
||||||
|
|
||||||
ReturnValue_t KeepAlivePduReader::parseData() {
|
ReturnValue_t KeepAlivePduReader::parseData() {
|
||||||
@ -14,4 +15,4 @@ ReturnValue_t KeepAlivePduReader::parseData() {
|
|||||||
return progress.deSerialize(&buffer, &remLen, getEndianness());
|
return progress.deSerialize(&buffer, &remLen, getEndianness());
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::Fss& KeepAlivePduReader::getProgress() { return progress; }
|
cfdp::FileSize& KeepAlivePduReader::getProgress() { return progress; }
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
#ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_
|
#ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_
|
||||||
#define FSFW_CFDP_PDU_KEEPALIVEREADER_H_
|
#define FSFW_CFDP_PDU_KEEPALIVEREADER_H_
|
||||||
|
|
||||||
#include "fsfw/cfdp/Fss.h"
|
#include "fsfw/cfdp/FileSize.h"
|
||||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||||
|
|
||||||
class KeepAlivePduReader : public FileDirectiveReader {
|
class KeepAlivePduReader : public FileDirectiveReader {
|
||||||
public:
|
public:
|
||||||
KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress);
|
KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::FileSize& progress);
|
||||||
|
|
||||||
ReturnValue_t parseData() override;
|
ReturnValue_t parseData() override;
|
||||||
|
|
||||||
cfdp::Fss& getProgress();
|
cfdp::FileSize& getProgress();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cfdp::Fss& progress;
|
cfdp::FileSize& progress;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */
|
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
#include "MetadataGenericInfo.h"
|
|
||||||
|
|
||||||
MetadataGenericInfo::MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType,
|
|
||||||
cfdp::Fss fileSize)
|
|
||||||
: MetadataGenericInfo(std::move(fileSize)) {
|
|
||||||
this->closureRequested = closureRequested;
|
|
||||||
this->checksumType = checksumType;
|
|
||||||
}
|
|
||||||
|
|
||||||
MetadataGenericInfo::MetadataGenericInfo(cfdp::Fss fileSize) : fileSize(std::move(fileSize)) {}
|
|
||||||
|
|
||||||
cfdp::ChecksumType MetadataGenericInfo::getChecksumType() const { return checksumType; }
|
|
||||||
|
|
||||||
void MetadataGenericInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
|
|
||||||
checksumType = checksumType_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MetadataGenericInfo::isClosureRequested() const { return closureRequested; }
|
|
||||||
|
|
||||||
void MetadataGenericInfo::setClosureRequested(bool closureRequested_) {
|
|
||||||
closureRequested = closureRequested_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfdp::Fss& MetadataGenericInfo::getFileSize() const { return fileSize; }
|
|
||||||
|
|
||||||
size_t MetadataGenericInfo::getSerializedSize(bool fssLarge) {
|
|
||||||
// 1 byte + minimal FSS 4 bytes
|
|
||||||
size_t size = 5;
|
|
||||||
if (fssLarge) {
|
|
||||||
size += 4;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfdp::Fss& MetadataGenericInfo::getMutFileSize() { return fileSize; }
|
|
@ -1,35 +0,0 @@
|
|||||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
|
|
||||||
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include "fsfw/cfdp/Fss.h"
|
|
||||||
#include "fsfw/cfdp/definitions.h"
|
|
||||||
#include "fsfw/cfdp/tlv/Lv.h"
|
|
||||||
#include "fsfw/cfdp/tlv/StringLv.h"
|
|
||||||
#include "fsfw/cfdp/tlv/Tlv.h"
|
|
||||||
|
|
||||||
class MetadataGenericInfo {
|
|
||||||
public:
|
|
||||||
MetadataGenericInfo() = default;
|
|
||||||
explicit MetadataGenericInfo(cfdp::Fss fileSize);
|
|
||||||
MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::Fss fileSize);
|
|
||||||
|
|
||||||
static size_t getSerializedSize(bool fssLarge = false);
|
|
||||||
|
|
||||||
[[nodiscard]] cfdp::ChecksumType getChecksumType() const;
|
|
||||||
void setChecksumType(cfdp::ChecksumType checksumType);
|
|
||||||
[[nodiscard]] bool isClosureRequested() const;
|
|
||||||
void setClosureRequested(bool closureRequested = false);
|
|
||||||
|
|
||||||
[[nodiscard]] const cfdp::Fss& getFileSize() const;
|
|
||||||
|
|
||||||
cfdp::Fss& getMutFileSize();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool closureRequested = false;
|
|
||||||
cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
|
|
||||||
cfdp::Fss fileSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */
|
|
103
src/fsfw/cfdp/pdu/MetadataInfo.cpp
Normal file
103
src/fsfw/cfdp/pdu/MetadataInfo.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "MetadataInfo.h"
|
||||||
|
|
||||||
|
MetadataInfo::MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType,
|
||||||
|
cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
|
||||||
|
cfdp::StringLv& destFileName)
|
||||||
|
: MetadataInfo(fileSize, sourceFileName, destFileName) {
|
||||||
|
this->closureRequested = closureRequested;
|
||||||
|
this->checksumType = checksumType;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetadataInfo::MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
|
||||||
|
cfdp::StringLv& destFileName)
|
||||||
|
: fileSize(fileSize), sourceFileName(sourceFileName), destFileName(destFileName) {}
|
||||||
|
|
||||||
|
void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray_, std::optional<size_t> optionsLen_,
|
||||||
|
std::optional<size_t> maxOptionsLen_) {
|
||||||
|
this->optionsArray = optionsArray_;
|
||||||
|
if (maxOptionsLen_) {
|
||||||
|
this->maxOptionsLen = maxOptionsLen_.value();
|
||||||
|
}
|
||||||
|
if (optionsLen_) {
|
||||||
|
this->optionsLen = optionsLen_.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfdp::ChecksumType MetadataInfo::getChecksumType() const { return checksumType; }
|
||||||
|
|
||||||
|
void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
|
||||||
|
checksumType = checksumType_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetadataInfo::isClosureRequested() const { return closureRequested; }
|
||||||
|
|
||||||
|
void MetadataInfo::setClosureRequested(bool closureRequested_) {
|
||||||
|
closureRequested = closureRequested_;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfdp::StringLv& MetadataInfo::getDestFileName() { return destFileName; }
|
||||||
|
|
||||||
|
cfdp::FileSize& MetadataInfo::getFileSize() { return fileSize; }
|
||||||
|
|
||||||
|
ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray_, size_t* optionsLen_,
|
||||||
|
size_t* maxOptsLen) {
|
||||||
|
if (optionsArray_ == nullptr or optionsArray == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
*optionsArray_ = optionsArray;
|
||||||
|
if (optionsLen_ != nullptr) {
|
||||||
|
*optionsLen_ = this->optionsLen;
|
||||||
|
}
|
||||||
|
if (maxOptsLen != nullptr) {
|
||||||
|
*maxOptsLen = this->maxOptionsLen;
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetadataInfo::hasOptions() const {
|
||||||
|
if (optionsArray != nullptr and optionsLen > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetadataInfo::canHoldOptions() const {
|
||||||
|
if (optionsArray != nullptr and maxOptionsLen > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MetadataInfo::getSerializedSize(bool fssLarge) {
|
||||||
|
// 1 byte + minimal FSS 4 bytes
|
||||||
|
size_t size = 5;
|
||||||
|
if (fssLarge) {
|
||||||
|
size += 4;
|
||||||
|
}
|
||||||
|
size += sourceFileName.getSerializedSize();
|
||||||
|
size += destFileName.getSerializedSize();
|
||||||
|
if (hasOptions()) {
|
||||||
|
for (size_t idx = 0; idx < optionsLen; idx++) {
|
||||||
|
size += optionsArray[idx]->getSerializedSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetadataInfo::setDestFileName(cfdp::StringLv& destFileName_) {
|
||||||
|
this->destFileName = destFileName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetadataInfo::setSourceFileName(cfdp::StringLv& sourceFileName_) {
|
||||||
|
this->sourceFileName = sourceFileName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MetadataInfo::getMaxOptionsLen() const { return maxOptionsLen; }
|
||||||
|
|
||||||
|
void MetadataInfo::setMaxOptionsLen(size_t maxOptionsLen_) { this->maxOptionsLen = maxOptionsLen_; }
|
||||||
|
|
||||||
|
size_t MetadataInfo::getOptionsLen() const { return optionsLen; }
|
||||||
|
|
||||||
|
void MetadataInfo::setOptionsLen(size_t optionsLen_) { this->optionsLen = optionsLen_; }
|
||||||
|
|
||||||
|
cfdp::StringLv& MetadataInfo::getSourceFileName() { return sourceFileName; }
|
55
src/fsfw/cfdp/pdu/MetadataInfo.h
Normal file
55
src/fsfw/cfdp/pdu/MetadataInfo.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
|
||||||
|
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "fsfw/cfdp/FileSize.h"
|
||||||
|
#include "fsfw/cfdp/definitions.h"
|
||||||
|
#include "fsfw/cfdp/tlv/Lv.h"
|
||||||
|
#include "fsfw/cfdp/tlv/StringLv.h"
|
||||||
|
#include "fsfw/cfdp/tlv/Tlv.h"
|
||||||
|
|
||||||
|
class MetadataInfo {
|
||||||
|
public:
|
||||||
|
MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
|
||||||
|
cfdp::StringLv& destFileName);
|
||||||
|
MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::FileSize& fileSize,
|
||||||
|
cfdp::StringLv& sourceFileName, cfdp::StringLv& destFileName);
|
||||||
|
|
||||||
|
size_t getSerializedSize(bool fssLarge = false);
|
||||||
|
|
||||||
|
void setOptionsArray(cfdp::Tlv** optionsArray, std::optional<size_t> optionsLen,
|
||||||
|
std::optional<size_t> maxOptionsLen);
|
||||||
|
[[nodiscard]] cfdp::ChecksumType getChecksumType() const;
|
||||||
|
void setChecksumType(cfdp::ChecksumType checksumType);
|
||||||
|
[[nodiscard]] bool isClosureRequested() const;
|
||||||
|
void setClosureRequested(bool closureRequested = false);
|
||||||
|
|
||||||
|
void setDestFileName(cfdp::StringLv& destFileName);
|
||||||
|
void setSourceFileName(cfdp::StringLv& sourceFileName);
|
||||||
|
|
||||||
|
cfdp::StringLv& getDestFileName();
|
||||||
|
cfdp::StringLv& getSourceFileName();
|
||||||
|
cfdp::FileSize& getFileSize();
|
||||||
|
|
||||||
|
[[nodiscard]] bool hasOptions() const;
|
||||||
|
[[nodiscard]] bool canHoldOptions() const;
|
||||||
|
ReturnValue_t getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen, size_t* maxOptsLen);
|
||||||
|
void setOptionsLen(size_t optionsLen);
|
||||||
|
[[nodiscard]] size_t getOptionsLen() const;
|
||||||
|
void setMaxOptionsLen(size_t maxOptionsLen);
|
||||||
|
[[nodiscard]] size_t getMaxOptionsLen() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool closureRequested = false;
|
||||||
|
cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
|
||||||
|
cfdp::FileSize& fileSize;
|
||||||
|
cfdp::StringLv& sourceFileName;
|
||||||
|
cfdp::StringLv& destFileName;
|
||||||
|
|
||||||
|
cfdp::Tlv** optionsArray = nullptr;
|
||||||
|
size_t optionsLen = 0;
|
||||||
|
size_t maxOptionsLen = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */
|
@ -1,26 +1,12 @@
|
|||||||
#include "MetadataPduCreator.h"
|
#include "MetadataPduCreator.h"
|
||||||
|
|
||||||
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataGenericInfo &info,
|
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataInfo &info)
|
||||||
cfdp::StringLv &srcFileName, cfdp::StringLv &destFileName,
|
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5), info(info) {
|
||||||
cfdp::Tlv **optionsArray, size_t optionsLen)
|
|
||||||
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5),
|
|
||||||
info(info),
|
|
||||||
srcFileName(srcFileName),
|
|
||||||
destFileName(destFileName),
|
|
||||||
optionsArray(optionsArray),
|
|
||||||
optionsLen(optionsLen) {
|
|
||||||
updateDirectiveFieldLen();
|
updateDirectiveFieldLen();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetadataPduCreator::updateDirectiveFieldLen() {
|
void MetadataPduCreator::updateDirectiveFieldLen() {
|
||||||
size_t dirFieldLen = MetadataGenericInfo::getSerializedSize(HeaderCreator::getLargeFileFlag()) +
|
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
|
||||||
srcFileName.getSerializedSize() + destFileName.getSerializedSize();
|
|
||||||
if (optionsLen > 0 and optionsArray != nullptr) {
|
|
||||||
for (size_t idx = 0; idx < optionsLen; idx++) {
|
|
||||||
dirFieldLen += optionsArray[idx]->getSerializedSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setDirectiveDataFieldLen(dirFieldLen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MetadataPduCreator::getSerializedSize() const {
|
size_t MetadataPduCreator::getSerializedSize() const {
|
||||||
@ -43,18 +29,21 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = srcFileName.serialize(buffer, size, maxSize, streamEndianness);
|
result = info.getSourceFileName().serialize(buffer, size, maxSize, streamEndianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = destFileName.serialize(buffer, size, maxSize, streamEndianness);
|
result = info.getDestFileName().serialize(buffer, size, maxSize, streamEndianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optionsLen > 0 and optionsArray != nullptr) {
|
if (info.hasOptions()) {
|
||||||
for (size_t idx = 0; idx < optionsLen; idx++) {
|
cfdp::Tlv **optsArray = nullptr;
|
||||||
result = optionsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
|
size_t optsLen = 0;
|
||||||
|
info.getOptions(&optsArray, &optsLen, nullptr);
|
||||||
|
for (size_t idx = 0; idx < optsLen; idx++) {
|
||||||
|
result = optsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -62,5 +51,3 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
const cfdp::StringLv &MetadataPduCreator::getSourceFileName() const { return srcFileName; }
|
|
||||||
const cfdp::StringLv &MetadataPduCreator::getDestFileName() const { return destFileName; }
|
|
||||||
|
@ -2,30 +2,22 @@
|
|||||||
#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
|
#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
|
||||||
|
|
||||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||||
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
|
#include "fsfw/cfdp/pdu/MetadataInfo.h"
|
||||||
|
|
||||||
class MetadataPduCreator : public FileDirectiveCreator {
|
class MetadataPduCreator : public FileDirectiveCreator {
|
||||||
public:
|
public:
|
||||||
MetadataPduCreator(PduConfig& conf, MetadataGenericInfo& info, cfdp::StringLv& srcFileName,
|
MetadataPduCreator(PduConfig& conf, MetadataInfo& info);
|
||||||
cfdp::StringLv& destFileName, cfdp::Tlv** optionsArray, size_t optionsLen);
|
|
||||||
|
|
||||||
void updateDirectiveFieldLen();
|
void updateDirectiveFieldLen();
|
||||||
|
|
||||||
[[nodiscard]] size_t getSerializedSize() const override;
|
[[nodiscard]] size_t getSerializedSize() const override;
|
||||||
|
|
||||||
const cfdp::StringLv& getSourceFileName() const;
|
|
||||||
const cfdp::StringLv& getDestFileName() const;
|
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override;
|
Endianness streamEndianness) const override;
|
||||||
using FileDirectiveCreator::serialize;
|
using FileDirectiveCreator::serialize;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MetadataGenericInfo& info;
|
MetadataInfo& info;
|
||||||
cfdp::StringLv& srcFileName;
|
|
||||||
cfdp::StringLv& destFileName;
|
|
||||||
cfdp::Tlv** optionsArray;
|
|
||||||
size_t optionsLen;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */
|
#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
#include "MetadataPduReader.h"
|
#include "MetadataPduReader.h"
|
||||||
|
|
||||||
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize,
|
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info)
|
||||||
MetadataGenericInfo& info, cfdp::Tlv* optionsArray,
|
: FileDirectiveReader(pduBuf, maxSize), info(info) {}
|
||||||
size_t optArrayMaxSize)
|
|
||||||
: FileDirectiveReader(pduBuf, maxSize),
|
|
||||||
info(info),
|
|
||||||
optionArray(optionsArray),
|
|
||||||
optionArrayMaxSize(optArrayMaxSize) {}
|
|
||||||
|
|
||||||
ReturnValue_t MetadataPduReader::parseData() {
|
ReturnValue_t MetadataPduReader::parseData() {
|
||||||
parsedOptions = 0;
|
|
||||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
@ -25,43 +19,39 @@ ReturnValue_t MetadataPduReader::parseData() {
|
|||||||
remSize -= 1;
|
remSize -= 1;
|
||||||
buf += 1;
|
buf += 1;
|
||||||
auto endianness = getEndianness();
|
auto endianness = getEndianness();
|
||||||
result = info.getMutFileSize().deSerialize(&buf, &remSize, endianness);
|
result = info.getFileSize().deSerialize(&buf, &remSize, endianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = srcFileName.deSerialize(&buf, &remSize, endianness);
|
result = info.getSourceFileName().deSerialize(&buf, &remSize, endianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = destFileName.deSerialize(&buf, &remSize, endianness);
|
result = info.getDestFileName().deSerialize(&buf, &remSize, endianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.setOptionsLen(0);
|
||||||
if (remSize > 0) {
|
if (remSize > 0) {
|
||||||
if (optionArrayMaxSize == 0 or optionArray == nullptr) {
|
if (not info.canHoldOptions()) {
|
||||||
return cfdp::METADATA_CANT_PARSE_OPTIONS;
|
return cfdp::METADATA_CANT_PARSE_OPTIONS;
|
||||||
}
|
}
|
||||||
|
cfdp::Tlv** optionsArray = nullptr;
|
||||||
|
size_t optsMaxLen = 0;
|
||||||
size_t optsIdx = 0;
|
size_t optsIdx = 0;
|
||||||
|
info.getOptions(&optionsArray, nullptr, &optsMaxLen);
|
||||||
while (remSize > 0) {
|
while (remSize > 0) {
|
||||||
if (optsIdx > optionArrayMaxSize) {
|
if (optsIdx > optsMaxLen) {
|
||||||
return cfdp::METADATA_CANT_PARSE_OPTIONS;
|
return cfdp::METADATA_CANT_PARSE_OPTIONS;
|
||||||
}
|
}
|
||||||
result = optionArray[optsIdx].deSerialize(&buf, &remSize, endianness);
|
result = optionsArray[optsIdx]->deSerialize(&buf, &remSize, endianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
optsIdx++;
|
optsIdx++;
|
||||||
}
|
}
|
||||||
parsedOptions = optsIdx;
|
info.setOptionsLen(optsIdx);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MetadataPduReader::getNumberOfParsedOptions() const { return parsedOptions; }
|
|
||||||
|
|
||||||
const cfdp::StringLv& MetadataPduReader::getSourceFileName() const { return srcFileName; }
|
|
||||||
|
|
||||||
const cfdp::StringLv& MetadataPduReader::getDestFileName() const { return destFileName; }
|
|
||||||
|
|
||||||
const MetadataGenericInfo& MetadataPduReader::getGenericInfo() const { return info; }
|
|
||||||
|
@ -2,28 +2,16 @@
|
|||||||
#define FSFW_CFDP_PDU_METADATAPDUREADER_H_
|
#define FSFW_CFDP_PDU_METADATAPDUREADER_H_
|
||||||
|
|
||||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||||
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
|
#include "fsfw/cfdp/pdu/MetadataInfo.h"
|
||||||
|
|
||||||
class MetadataPduReader : public FileDirectiveReader {
|
class MetadataPduReader : public FileDirectiveReader {
|
||||||
public:
|
public:
|
||||||
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataGenericInfo& info,
|
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info);
|
||||||
cfdp::Tlv* optionsArray, size_t optArrayMaxSize);
|
|
||||||
|
|
||||||
ReturnValue_t parseData() override;
|
ReturnValue_t parseData() override;
|
||||||
|
|
||||||
[[nodiscard]] const MetadataGenericInfo& getGenericInfo() const;
|
|
||||||
[[nodiscard]] const cfdp::StringLv& getSourceFileName() const;
|
|
||||||
[[nodiscard]] const cfdp::StringLv& getDestFileName() const;
|
|
||||||
|
|
||||||
[[nodiscard]] size_t getNumberOfParsedOptions() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cfdp::StringLv srcFileName;
|
MetadataInfo& info;
|
||||||
cfdp::StringLv destFileName;
|
|
||||||
MetadataGenericInfo& info;
|
|
||||||
cfdp::Tlv* optionArray;
|
|
||||||
size_t optionArrayMaxSize;
|
|
||||||
size_t parsedOptions = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */
|
#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "NakInfo.h"
|
#include "NakInfo.h"
|
||||||
|
|
||||||
NakInfo::NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope)
|
NakInfo::NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope)
|
||||||
: startOfScope(startOfScope), endOfScope(endOfScope) {}
|
: startOfScope(startOfScope), endOfScope(endOfScope) {}
|
||||||
|
|
||||||
size_t NakInfo::getSerializedSize(bool fssLarge) {
|
size_t NakInfo::getSerializedSize(bool fssLarge) {
|
||||||
@ -57,9 +57,9 @@ void NakInfo::setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::Fss& NakInfo::getStartOfScope() { return startOfScope; }
|
cfdp::FileSize& NakInfo::getStartOfScope() { return startOfScope; }
|
||||||
|
|
||||||
cfdp::Fss& NakInfo::getEndOfScope() { return endOfScope; }
|
cfdp::FileSize& NakInfo::getEndOfScope() { return endOfScope; }
|
||||||
|
|
||||||
size_t NakInfo::getSegmentRequestsLen() const { return segmentRequestsLen; }
|
size_t NakInfo::getSegmentRequestsLen() const { return segmentRequestsLen; }
|
||||||
|
|
||||||
|
@ -3,21 +3,21 @@
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "fsfw/cfdp/Fss.h"
|
#include "fsfw/cfdp/FileSize.h"
|
||||||
|
|
||||||
class NakInfo {
|
class NakInfo {
|
||||||
public:
|
public:
|
||||||
using SegmentRequest = std::pair<cfdp::Fss, cfdp::Fss>;
|
using SegmentRequest = std::pair<cfdp::FileSize, cfdp::FileSize>;
|
||||||
|
|
||||||
NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope);
|
NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope);
|
||||||
|
|
||||||
void setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmentRequestLen,
|
void setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmentRequestLen,
|
||||||
size_t* maxSegmentRequestLen);
|
size_t* maxSegmentRequestLen);
|
||||||
|
|
||||||
size_t getSerializedSize(bool fssLarge = false);
|
size_t getSerializedSize(bool fssLarge = false);
|
||||||
|
|
||||||
cfdp::Fss& getStartOfScope();
|
cfdp::FileSize& getStartOfScope();
|
||||||
cfdp::Fss& getEndOfScope();
|
cfdp::FileSize& getEndOfScope();
|
||||||
|
|
||||||
bool hasSegmentRequests() const;
|
bool hasSegmentRequests() const;
|
||||||
bool canHoldSegmentRequests() const;
|
bool canHoldSegmentRequests() const;
|
||||||
@ -31,8 +31,8 @@ class NakInfo {
|
|||||||
void setSegmentRequestLen(size_t readLen);
|
void setSegmentRequestLen(size_t readLen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cfdp::Fss startOfScope;
|
cfdp::FileSize startOfScope;
|
||||||
cfdp::Fss endOfScope;
|
cfdp::FileSize endOfScope;
|
||||||
SegmentRequest* segmentRequests = nullptr;
|
SegmentRequest* segmentRequests = nullptr;
|
||||||
size_t segmentRequestsLen = 0;
|
size_t segmentRequestsLen = 0;
|
||||||
size_t maxSegmentRequestsLen = 0;
|
size_t maxSegmentRequestsLen = 0;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "NakInfo.h"
|
#include "NakInfo.h"
|
||||||
#include "fsfw/cfdp/Fss.h"
|
#include "fsfw/cfdp/FileSize.h"
|
||||||
#include "fsfw/cfdp/definitions.h"
|
#include "fsfw/cfdp/definitions.h"
|
||||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||||
|
|
||||||
|
@ -105,8 +105,7 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
|
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
|
||||||
static void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width,
|
void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const;
|
||||||
void* sourcePtr);
|
|
||||||
void* sourceIdRaw = nullptr;
|
void* sourceIdRaw = nullptr;
|
||||||
void* seqNumRaw = nullptr;
|
void* seqNumRaw = nullptr;
|
||||||
void* destIdRaw = nullptr;
|
void* destIdRaw = nullptr;
|
||||||
|
@ -8,5 +8,4 @@ target_sources(
|
|||||||
StringLv.cpp
|
StringLv.cpp
|
||||||
FlowLabelTlv.cpp
|
FlowLabelTlv.cpp
|
||||||
MessageToUserTlv.cpp
|
MessageToUserTlv.cpp
|
||||||
FaultHandlerOverrideTlv.cpp
|
FaultHandlerOverrideTlv.cpp)
|
||||||
ReservedMessageCreator.cpp)
|
|
||||||
|
@ -23,8 +23,7 @@ class EntityIdTlv : public TlvIF {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
|
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
|
||||||
|
|
||||||
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
|
using SerializeIF::deSerialize;
|
||||||
// the compiler
|
|
||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
|
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
|
||||||
|
|
||||||
|
using SerializeIF::deSerialize;
|
||||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
|
@ -29,8 +29,7 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
|
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
|
||||||
|
|
||||||
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
|
using SerializeIF::deSerialize;
|
||||||
// the compiler
|
|
||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
|
@ -14,6 +14,23 @@ cfdp::Lv::Lv(const std::vector<uint8_t>& data) : value(data.data(), data.size(),
|
|||||||
|
|
||||||
cfdp::Lv::Lv() : value(static_cast<uint8_t*>(nullptr), 0, true) {}
|
cfdp::Lv::Lv() : value(static_cast<uint8_t*>(nullptr), 0, true) {}
|
||||||
|
|
||||||
|
cfdp::Lv::Lv(const Lv& other)
|
||||||
|
: value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
|
||||||
|
if (other.value.getSerializedSize() - 1 > 0) {
|
||||||
|
zeroLen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfdp::Lv& cfdp::Lv::operator=(const Lv& other) {
|
||||||
|
size_t otherSize = 0;
|
||||||
|
auto* otherVal = const_cast<uint8_t*>(other.getValue(&otherSize));
|
||||||
|
if (otherVal == nullptr or otherSize == 0) {
|
||||||
|
this->zeroLen = true;
|
||||||
|
}
|
||||||
|
this->value.setConstBuffer(otherVal, otherSize);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
Endianness streamEndianness) const {
|
Endianness streamEndianness) const {
|
||||||
if (maxSize < 1) {
|
if (maxSize < 1) {
|
||||||
@ -32,8 +49,10 @@ ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t cfdp::Lv::getSerializedSize() const {
|
size_t cfdp::Lv::getSerializedSize() const {
|
||||||
if (zeroLen or value.getConstBuffer() == nullptr) {
|
if (zeroLen) {
|
||||||
return 1;
|
return 1;
|
||||||
|
} else if (value.getConstBuffer() == nullptr) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return value.getSerializedSize();
|
return value.getSerializedSize();
|
||||||
}
|
}
|
||||||
@ -66,34 +85,7 @@ ReturnValue_t cfdp::Lv::deSerialize(const uint8_t** buffer, size_t* size,
|
|||||||
const uint8_t* cfdp::Lv::getValue(size_t* size) const {
|
const uint8_t* cfdp::Lv::getValue(size_t* size) const {
|
||||||
if (size != nullptr) {
|
if (size != nullptr) {
|
||||||
// Length without length field
|
// Length without length field
|
||||||
*size = getSerializedSize() - 1;
|
*size = value.getSerializedSize() - 1;
|
||||||
}
|
}
|
||||||
return value.getConstBuffer();
|
return value.getConstBuffer();
|
||||||
}
|
}
|
||||||
cfdp::Lv::Lv(cfdp::Lv&& other) noexcept
|
|
||||||
: value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
|
|
||||||
if (other.value.getSerializedSize() - 1 > 0) {
|
|
||||||
zeroLen = false;
|
|
||||||
}
|
|
||||||
// Leave other class in intact state.
|
|
||||||
other.zeroLen = false;
|
|
||||||
other.value = SerialBufferAdapter<uint8_t>();
|
|
||||||
}
|
|
||||||
|
|
||||||
cfdp::Lv& cfdp::Lv::operator=(cfdp::Lv&& other) noexcept {
|
|
||||||
size_t otherSize = 0;
|
|
||||||
this->zeroLen = false;
|
|
||||||
auto* otherVal = const_cast<uint8_t*>(other.getValue(&otherSize));
|
|
||||||
if (otherVal == nullptr or otherSize == 0) {
|
|
||||||
this->zeroLen = true;
|
|
||||||
}
|
|
||||||
this->value.setConstBuffer(otherVal, otherSize);
|
|
||||||
// Leave other class in intact state.
|
|
||||||
other.zeroLen = false;
|
|
||||||
other.value = SerialBufferAdapter<uint8_t>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cfdp::Lv::getValueLen() const { return getSerializedSize() - 1; }
|
|
||||||
|
|
||||||
bool cfdp::Lv::isEmpty() const { return zeroLen; }
|
|
||||||
|
@ -18,12 +18,8 @@ class Lv : public SerializeIF {
|
|||||||
Lv(const uint8_t* value, size_t size);
|
Lv(const uint8_t* value, size_t size);
|
||||||
Lv();
|
Lv();
|
||||||
|
|
||||||
// Semantically, this class is a zero-copy helper, so the copy ctor and copy assigment do not
|
Lv(const Lv&);
|
||||||
// really make sense here.
|
Lv& operator=(const Lv&);
|
||||||
Lv(const Lv&) = delete;
|
|
||||||
Lv& operator=(const Lv&) = delete;
|
|
||||||
Lv(Lv&&) noexcept;
|
|
||||||
Lv& operator=(Lv&&) noexcept;
|
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override;
|
Endianness streamEndianness) const override;
|
||||||
@ -40,8 +36,6 @@ class Lv : public SerializeIF {
|
|||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
size_t getValueLen() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get value field and its size.
|
* Get value field and its size.
|
||||||
* @param size Optionally retrieve size. Size will be the size of the actual value field
|
* @param size Optionally retrieve size. Size will be the size of the actual value field
|
||||||
@ -50,8 +44,6 @@ class Lv : public SerializeIF {
|
|||||||
*/
|
*/
|
||||||
const uint8_t* getValue(size_t* size) const;
|
const uint8_t* getValue(size_t* size) const;
|
||||||
|
|
||||||
bool isEmpty() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool zeroLen = true;
|
bool zeroLen = true;
|
||||||
SerialBufferAdapter<uint8_t> value;
|
SerialBufferAdapter<uint8_t> value;
|
||||||
|
@ -7,22 +7,3 @@ MessageToUserTlv::MessageToUserTlv() : Tlv() {}
|
|||||||
|
|
||||||
MessageToUserTlv::MessageToUserTlv(const std::vector<uint8_t>& data)
|
MessageToUserTlv::MessageToUserTlv(const std::vector<uint8_t>& data)
|
||||||
: Tlv(cfdp::TlvType::MSG_TO_USER, data.data(), data.size()) {}
|
: Tlv(cfdp::TlvType::MSG_TO_USER, data.data(), data.size()) {}
|
||||||
|
|
||||||
MessageToUserTlv::MessageToUserTlv(const uint8_t* value, size_t size)
|
|
||||||
: Tlv(cfdp::TlvType::MSG_TO_USER, value, size) {}
|
|
||||||
|
|
||||||
bool MessageToUserTlv::isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
|
|
||||||
size_t& msgLen) const {
|
|
||||||
if (cfdp::Tlv::getLengthField() < 5) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (std::strncmp(reinterpret_cast<const char*>(getValue()), "cfdp", 4) == 0) {
|
|
||||||
messageType = getValue()[4];
|
|
||||||
if (msgDataStart != nullptr) {
|
|
||||||
*msgDataStart = getValue() + 5;
|
|
||||||
}
|
|
||||||
msgLen = cfdp::Tlv::getSerializedSize() - 5;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
@ -9,12 +9,8 @@ class MessageToUserTlv : public cfdp::Tlv {
|
|||||||
public:
|
public:
|
||||||
MessageToUserTlv();
|
MessageToUserTlv();
|
||||||
MessageToUserTlv(uint8_t* value, size_t size);
|
MessageToUserTlv(uint8_t* value, size_t size);
|
||||||
MessageToUserTlv(const uint8_t* value, size_t size);
|
|
||||||
explicit MessageToUserTlv(const std::vector<uint8_t>& data);
|
explicit MessageToUserTlv(const std::vector<uint8_t>& data);
|
||||||
|
|
||||||
bool isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
|
|
||||||
size_t& msgLen) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
#include "ReservedMessageCreator.h"
|
|
||||||
|
|
||||||
cfdp::ReservedMessageCreator::ReservedMessageCreator(uint8_t messageType, uint8_t *msgData,
|
|
||||||
size_t msgLen)
|
|
||||||
: messageType(messageType), msgData(msgData), msgSize(msgLen) {}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::ReservedMessageCreator::serialize(
|
|
||||||
uint8_t **buffer, size_t *size, size_t maxSize,
|
|
||||||
SerializeIF::Endianness streamEndianness) const {
|
|
||||||
if (*size + getSerializedSize() > maxSize) {
|
|
||||||
return SerializeIF::BUFFER_TOO_SHORT;
|
|
||||||
}
|
|
||||||
**buffer = TlvType::MSG_TO_USER;
|
|
||||||
*buffer += 1;
|
|
||||||
*size += 1;
|
|
||||||
**buffer = getSerializedSize() - 2;
|
|
||||||
*size += 1;
|
|
||||||
*buffer += 1;
|
|
||||||
std::memcpy(*buffer, MSG_HEADER, 4);
|
|
||||||
*buffer += 4;
|
|
||||||
*size += 4;
|
|
||||||
**buffer = messageType;
|
|
||||||
*buffer += 1;
|
|
||||||
*size += 1;
|
|
||||||
std::memcpy(*buffer, msgData, msgSize);
|
|
||||||
*buffer += msgSize;
|
|
||||||
*size += msgSize;
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cfdp::ReservedMessageCreator::getSerializedSize() const {
|
|
||||||
// 2 bytes type and length, 4 bytes CFDP, 1 byte reserved message type, message data.
|
|
||||||
return 2 + 5 + msgSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t cfdp::ReservedMessageCreator::deSerialize(const uint8_t **buffer, size_t *size,
|
|
||||||
SerializeIF::Endianness streamEndianness) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Tlv.h"
|
|
||||||
|
|
||||||
namespace cfdp {
|
|
||||||
|
|
||||||
class ReservedMessageCreator : public SerializeIF {
|
|
||||||
public:
|
|
||||||
static constexpr char MSG_HEADER[] = "cfdp";
|
|
||||||
|
|
||||||
ReservedMessageCreator(uint8_t messageType, uint8_t *msgData, size_t msgLen);
|
|
||||||
[[nodiscard]] ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
|
||||||
Endianness streamEndianness) const override;
|
|
||||||
[[nodiscard]] size_t getSerializedSize() const override;
|
|
||||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
|
||||||
Endianness streamEndianness) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t messageType;
|
|
||||||
uint8_t *msgData;
|
|
||||||
size_t msgSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cfdp
|
|
@ -7,12 +7,3 @@ cfdp::StringLv::StringLv(const char* filename, size_t len)
|
|||||||
: Lv(reinterpret_cast<const uint8_t*>(filename), len) {}
|
: Lv(reinterpret_cast<const uint8_t*>(filename), len) {}
|
||||||
|
|
||||||
cfdp::StringLv::StringLv() : Lv() {}
|
cfdp::StringLv::StringLv() : Lv() {}
|
||||||
|
|
||||||
const char* cfdp::StringLv::getCString(size_t& fileSize) const {
|
|
||||||
return reinterpret_cast<const char*>(getValue(&fileSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string cfdp::StringLv::getString() const {
|
|
||||||
size_t fileSize;
|
|
||||||
return {getCString(fileSize), fileSize};
|
|
||||||
}
|
|
||||||
|
@ -13,8 +13,6 @@ class StringLv : public Lv {
|
|||||||
explicit StringLv(const std::string& fileName);
|
explicit StringLv(const std::string& fileName);
|
||||||
explicit StringLv(const char* filename, size_t len);
|
explicit StringLv(const char* filename, size_t len);
|
||||||
|
|
||||||
const char* getCString(size_t& fileSize) const;
|
|
||||||
std::string getString() const;
|
|
||||||
// Delete the move constructor to avoid passing in a temporary
|
// Delete the move constructor to avoid passing in a temporary
|
||||||
StringLv(const std::string&&) = delete;
|
StringLv(const std::string&&) = delete;
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,6 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
|
|||||||
return STREAM_TOO_SHORT;
|
return STREAM_TOO_SHORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
rawData = *buffer;
|
|
||||||
uint8_t rawType = **buffer;
|
uint8_t rawType = **buffer;
|
||||||
if (not checkType(rawType)) {
|
if (not checkType(rawType)) {
|
||||||
return INVALID_TLV_TYPE;
|
return INVALID_TLV_TYPE;
|
||||||
@ -103,5 +102,3 @@ void cfdp::Tlv::setValue(uint8_t *value, size_t len) {
|
|||||||
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }
|
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }
|
||||||
|
|
||||||
void cfdp::Tlv::setType(TlvType type) { this->type = type; }
|
void cfdp::Tlv::setType(TlvType type) { this->type = type; }
|
||||||
|
|
||||||
const uint8_t *cfdp::Tlv::getRawData() const { return rawData; }
|
|
||||||
|
@ -47,7 +47,6 @@ class Tlv : public TlvIF {
|
|||||||
void setValue(uint8_t *value, size_t len);
|
void setValue(uint8_t *value, size_t len);
|
||||||
|
|
||||||
[[nodiscard]] const uint8_t *getValue() const;
|
[[nodiscard]] const uint8_t *getValue() const;
|
||||||
[[nodiscard]] const uint8_t *getRawData() const;
|
|
||||||
void setType(TlvType type);
|
void setType(TlvType type);
|
||||||
[[nodiscard]] TlvType getType() const override;
|
[[nodiscard]] TlvType getType() const override;
|
||||||
[[nodiscard]] uint8_t getLengthField() const override;
|
[[nodiscard]] uint8_t getLengthField() const override;
|
||||||
@ -56,7 +55,6 @@ class Tlv : public TlvIF {
|
|||||||
bool checkType(uint8_t rawType);
|
bool checkType(uint8_t rawType);
|
||||||
|
|
||||||
bool zeroLen = true;
|
bool zeroLen = true;
|
||||||
const uint8_t *rawData = nullptr;
|
|
||||||
TlvType type = TlvType::INVALID_TLV;
|
TlvType type = TlvType::INVALID_TLV;
|
||||||
SerialBufferAdapter<uint8_t> value;
|
SerialBufferAdapter<uint8_t> value;
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
template <typename Tp>
|
template <typename Tp>
|
||||||
class BinaryNode {
|
class BinaryNode {
|
||||||
public:
|
public:
|
||||||
BinaryNode(Tp* setValue) : value(setValue), left(NULL), right(NULL), parent(NULL) {}
|
BinaryNode(Tp* setValue) : value(setValue), left(nullptr), right(nullptr), parent(nullptr) {}
|
||||||
Tp* value;
|
Tp* value;
|
||||||
BinaryNode* left;
|
BinaryNode* left;
|
||||||
BinaryNode* right;
|
BinaryNode* right;
|
||||||
@ -23,31 +23,31 @@ class ExplicitNodeIterator {
|
|||||||
typedef Tp value_type;
|
typedef Tp value_type;
|
||||||
typedef Tp* pointer;
|
typedef Tp* pointer;
|
||||||
typedef Tp& reference;
|
typedef Tp& reference;
|
||||||
ExplicitNodeIterator() : element(NULL) {}
|
ExplicitNodeIterator() : element(nullptr) {}
|
||||||
ExplicitNodeIterator(_Node* node) : element(node) {}
|
ExplicitNodeIterator(_Node* node) : element(node) {}
|
||||||
BinaryNode<Tp>* element;
|
BinaryNode<Tp>* element;
|
||||||
_Self up() { return _Self(element->parent); }
|
_Self up() { return _Self(element->parent); }
|
||||||
_Self left() {
|
_Self left() {
|
||||||
if (element != NULL) {
|
if (element != nullptr) {
|
||||||
return _Self(element->left);
|
return _Self(element->left);
|
||||||
} else {
|
} else {
|
||||||
return _Self(NULL);
|
return _Self(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_Self right() {
|
_Self right() {
|
||||||
if (element != NULL) {
|
if (element != nullptr) {
|
||||||
return _Self(element->right);
|
return _Self(element->right);
|
||||||
} else {
|
} else {
|
||||||
return _Self(NULL);
|
return _Self(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool operator==(const _Self& __x) const { return element == __x.element; }
|
bool operator==(const _Self& __x) const { return element == __x.element; }
|
||||||
bool operator!=(const _Self& __x) const { return element != __x.element; }
|
bool operator!=(const _Self& __x) const { return element != __x.element; }
|
||||||
pointer operator->() const {
|
pointer operator->() const {
|
||||||
if (element != NULL) {
|
if (element != nullptr) {
|
||||||
return element->value;
|
return element->value;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pointer operator*() const { return this->operator->(); }
|
pointer operator*() const { return this->operator->(); }
|
||||||
@ -62,13 +62,13 @@ class BinaryTree {
|
|||||||
typedef ExplicitNodeIterator<Tp> iterator;
|
typedef ExplicitNodeIterator<Tp> iterator;
|
||||||
typedef BinaryNode<Tp> Node;
|
typedef BinaryNode<Tp> Node;
|
||||||
typedef std::pair<iterator, iterator> children;
|
typedef std::pair<iterator, iterator> children;
|
||||||
BinaryTree() : rootNode(NULL) {}
|
BinaryTree() : rootNode(nullptr) {}
|
||||||
BinaryTree(Node* rootNode) : rootNode(rootNode) {}
|
BinaryTree(Node* rootNode) : rootNode(rootNode) {}
|
||||||
iterator begin() const { return iterator(rootNode); }
|
iterator begin() const { return iterator(rootNode); }
|
||||||
static iterator end() { return iterator(NULL); }
|
static iterator end() { return iterator(nullptr); }
|
||||||
iterator insert(bool insertLeft, iterator parentNode, Node* newNode) {
|
iterator insert(bool insertLeft, iterator parentNode, Node* newNode) {
|
||||||
newNode->parent = parentNode.element;
|
newNode->parent = parentNode.element;
|
||||||
if (parentNode.element != NULL) {
|
if (parentNode.element != nullptr) {
|
||||||
if (insertLeft) {
|
if (insertLeft) {
|
||||||
parentNode.element->left = newNode;
|
parentNode.element->left = newNode;
|
||||||
} else {
|
} else {
|
||||||
@ -84,13 +84,13 @@ class BinaryTree {
|
|||||||
children erase(iterator node) {
|
children erase(iterator node) {
|
||||||
if (node.element == rootNode) {
|
if (node.element == rootNode) {
|
||||||
// We're root node
|
// We're root node
|
||||||
rootNode = NULL;
|
rootNode = nullptr;
|
||||||
} else {
|
} else {
|
||||||
// Delete parent's reference
|
// Delete parent's reference
|
||||||
if (node.up().left() == node) {
|
if (node.up().left() == node) {
|
||||||
node.up().element->left = NULL;
|
node.up().element->left = nullptr;
|
||||||
} else {
|
} else {
|
||||||
node.up().element->right = NULL;
|
node.up().element->right = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return children(node.element->left, node.element->right);
|
return children(node.element->left, node.element->right);
|
||||||
|
@ -12,7 +12,6 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
|||||||
class FixedArrayList : public ArrayList<T, count_t> {
|
class FixedArrayList : public ArrayList<T, count_t> {
|
||||||
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||||
"count_t is not large enough to hold MAX_SIZE");
|
"count_t is not large enough to hold MAX_SIZE");
|
||||||
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
|
@ -155,8 +155,8 @@ class FixedMap : public SerializeIF {
|
|||||||
|
|
||||||
uint32_t maxSize() const { return theMap.maxSize(); }
|
uint32_t maxSize() const { return theMap.maxSize(); }
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override {
|
Endianness streamEndianness) const {
|
||||||
ReturnValue_t result =
|
ReturnValue_t result =
|
||||||
SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness);
|
SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness);
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
@ -170,7 +170,7 @@ class FixedMap : public SerializeIF {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getSerializedSize() const override {
|
virtual size_t getSerializedSize() const {
|
||||||
uint32_t printSize = sizeof(_size);
|
uint32_t printSize = sizeof(_size);
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
@ -182,8 +182,8 @@ class FixedMap : public SerializeIF {
|
|||||||
return printSize;
|
return printSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) override {
|
Endianness streamEndianness) {
|
||||||
ReturnValue_t result =
|
ReturnValue_t result =
|
||||||
SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness);
|
SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness);
|
||||||
if (this->_size > theMap.maxSize()) {
|
if (this->_size > theMap.maxSize()) {
|
||||||
|
@ -61,7 +61,7 @@ class PlacementFactory {
|
|||||||
// Need to call destructor first, in case something was allocated by the object (shouldn't do
|
// Need to call destructor first, in case something was allocated by the object (shouldn't do
|
||||||
// that, however).
|
// that, however).
|
||||||
thisElement->~T();
|
thisElement->~T();
|
||||||
uint8_t* pointer = (uint8_t*)(thisElement);
|
uint8_t* pointer = static_cast<uint8_t*>(thisElement);
|
||||||
return dataBackend->deleteData(pointer, sizeof(T));
|
return dataBackend->deleteData(pointer, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "fsfw/container/SharedRingBuffer.h"
|
#include "fsfw/container/SharedRingBuffer.h"
|
||||||
|
|
||||||
#include "SharedRingBuffer.h"
|
|
||||||
#include "fsfw/ipc/MutexFactory.h"
|
#include "fsfw/ipc/MutexFactory.h"
|
||||||
#include "fsfw/ipc/MutexGuard.h"
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
|
|
||||||
@ -16,12 +15,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const
|
|||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedRingBuffer::~SharedRingBuffer() {
|
SharedRingBuffer::~SharedRingBuffer() { MutexFactory::instance()->deleteMutex(mutex); }
|
||||||
MutexFactory::instance()->deleteMutex(mutex);
|
|
||||||
if (receiveSizesFifo != nullptr) {
|
|
||||||
delete (receiveSizesFifo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { this->fifoDepth = fifoDepth; }
|
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { this->fifoDepth = fifoDepth; }
|
||||||
|
|
||||||
@ -36,31 +30,18 @@ MutexIF* SharedRingBuffer::getMutexHandle() const { return mutex; }
|
|||||||
|
|
||||||
ReturnValue_t SharedRingBuffer::initialize() {
|
ReturnValue_t SharedRingBuffer::initialize() {
|
||||||
if (fifoDepth > 0) {
|
if (fifoDepth > 0) {
|
||||||
receiveSizesFifo = new DynamicFIFO<size_t>(fifoDepth);
|
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
||||||
}
|
}
|
||||||
return SystemObject::initialize();
|
return SystemObject::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFifo() {
|
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
||||||
if (receiveSizesFifo == nullptr) {
|
if (receiveSizesFIFO == nullptr) {
|
||||||
// Configuration error.
|
// Configuration error.
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
||||||
<< " was not configured to have sizes FIFO, returning nullptr!" << std::endl;
|
<< " was not configured to have sizes FIFO, returning nullptr!" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return receiveSizesFifo;
|
return receiveSizesFIFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedRingBuffer::fifoEmpty(bool& empty, MutexIF::TimeoutType timeoutType,
|
|
||||||
uint32_t timeoutMs) {
|
|
||||||
if (receiveSizesFifo == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
MutexGuard mg(mutex, timeoutType, timeoutMs);
|
|
||||||
if (mg.getLockResult() != returnvalue::OK) {
|
|
||||||
return mg.getLockResult();
|
|
||||||
}
|
|
||||||
empty = receiveSizesFifo->empty();
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
@ -20,7 +20,7 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
|
|||||||
* This constructor allocates a new internal buffer with the supplied size.
|
* This constructor allocates a new internal buffer with the supplied size.
|
||||||
* @param size
|
* @param size
|
||||||
* @param overwriteOld
|
* @param overwriteOld
|
||||||
* If the ring buffer is overflowing at a write operation, the oldest data
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
* will be overwritten.
|
* will be overwritten.
|
||||||
*/
|
*/
|
||||||
SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld,
|
SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld,
|
||||||
@ -30,7 +30,7 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
|
|||||||
* @param buffer
|
* @param buffer
|
||||||
* @param size
|
* @param size
|
||||||
* @param overwriteOld
|
* @param overwriteOld
|
||||||
* If the ring buffer is overflowing at a write operation, the oldest data
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
* will be overwritten.
|
* will be overwritten.
|
||||||
*/
|
*/
|
||||||
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size, bool overwriteOld,
|
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size, bool overwriteOld,
|
||||||
@ -78,15 +78,13 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
|
|||||||
* Do not forget to protect access with a lock if required!
|
* Do not forget to protect access with a lock if required!
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
DynamicFIFO<size_t>* getReceiveSizesFifo();
|
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
||||||
|
|
||||||
ReturnValue_t fifoEmpty(bool& empty, MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
|
|
||||||
size_t fifoDepth = 0;
|
size_t fifoDepth = 0;
|
||||||
DynamicFIFO<size_t>* receiveSizesFifo = nullptr;
|
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */
|
#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */
|
||||||
|
@ -4,31 +4,48 @@
|
|||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/subsystem/SubsystemBase.h"
|
#include "fsfw/subsystem/SubsystemBase.h"
|
||||||
#include "fsfw/subsystem/helper.h"
|
|
||||||
|
|
||||||
ControllerBase::ControllerBase(object_id_t setObjectId, size_t commandQueueDepth)
|
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||||
|
size_t commandQueueDepth)
|
||||||
: SystemObject(setObjectId),
|
: SystemObject(setObjectId),
|
||||||
|
parentId(parentId),
|
||||||
mode(MODE_OFF),
|
mode(MODE_OFF),
|
||||||
submode(SUBMODE_NONE),
|
submode(SUBMODE_NONE),
|
||||||
modeHelper(this),
|
modeHelper(this),
|
||||||
healthHelper(this, setObjectId) {
|
healthHelper(this, setObjectId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::initialize() {
|
ReturnValue_t ControllerBase::initialize() {
|
||||||
ReturnValue_t result = modeHelper.initialize();
|
ReturnValue_t result = SystemObject::initialize();
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = healthHelper.initialize();
|
|
||||||
|
MessageQueueId_t parentQueue = 0;
|
||||||
|
if (parentId != objects::NO_OBJECT) {
|
||||||
|
auto* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
||||||
|
if (parent == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
parentQueue = parent->getCommandQueue();
|
||||||
|
|
||||||
|
parent->registerChild(getObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
result = healthHelper.initialize(parentQueue);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return SystemObject::initialize();
|
|
||||||
|
result = modeHelper.initialize(parentQueue);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
|
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
|
||||||
@ -58,7 +75,7 @@ void ControllerBase::handleQueue() {
|
|||||||
|
|
||||||
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
|
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
|
||||||
changeHK(this->mode, this->submode, false);
|
changeHK(this->mode, this->submode, false);
|
||||||
triggerEvent(CHANGING_MODE, mode_, submode_);
|
triggerEvent(CHANGING_MODE, mode, submode);
|
||||||
mode = mode_;
|
mode = mode_;
|
||||||
submode = submode_;
|
submode = submode_;
|
||||||
modeHelper.modeChanged(mode, submode);
|
modeHelper.modeChanged(mode, submode);
|
||||||
@ -72,17 +89,18 @@ void ControllerBase::getMode(Mode_t* mode_, Submode_t* submode_) {
|
|||||||
*submode_ = this->submode;
|
*submode_ = this->submode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
|
|
||||||
|
|
||||||
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
|
|
||||||
|
|
||||||
void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); }
|
void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); }
|
||||||
|
|
||||||
|
void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||||
handleQueue();
|
handleQueue();
|
||||||
performControlOperation(opCode);
|
performControlOperation();
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||||
switch (health) {
|
switch (health) {
|
||||||
case HEALTHY:
|
case HEALTHY:
|
||||||
@ -100,13 +118,3 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
|
|||||||
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
|
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
|
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
|
||||||
|
|
||||||
const HasHealthIF* ControllerBase::getOptHealthIF() const { return this; }
|
|
||||||
|
|
||||||
const HasModesIF& ControllerBase::getModeIF() const { return *this; }
|
|
||||||
|
|
||||||
ModeTreeChildIF& ControllerBase::getModeTreeChildIF() { return *this; }
|
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
|
|
||||||
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
|
|
||||||
}
|
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
#include "fsfw/modes/HasModesIF.h"
|
#include "fsfw/modes/HasModesIF.h"
|
||||||
#include "fsfw/modes/ModeHelper.h"
|
#include "fsfw/modes/ModeHelper.h"
|
||||||
#include "fsfw/objectmanager/SystemObject.h"
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
|
|
||||||
#include "fsfw/subsystem/ModeTreeChildIF.h"
|
|
||||||
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
|
|
||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
@ -21,18 +18,13 @@
|
|||||||
class ControllerBase : public HasModesIF,
|
class ControllerBase : public HasModesIF,
|
||||||
public HasHealthIF,
|
public HasHealthIF,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
public ModeTreeChildIF,
|
|
||||||
public ModeTreeConnectionIF,
|
|
||||||
public SystemObject {
|
public SystemObject {
|
||||||
public:
|
public:
|
||||||
static const Mode_t MODE_NORMAL = 2;
|
static const Mode_t MODE_NORMAL = 2;
|
||||||
|
|
||||||
ControllerBase(object_id_t setObjectId, size_t commandQueueDepth = 3);
|
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
|
||||||
~ControllerBase() override;
|
~ControllerBase() override;
|
||||||
|
|
||||||
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
|
|
||||||
ModeTreeChildIF &getModeTreeChildIF() override;
|
|
||||||
|
|
||||||
/** SystemObject override */
|
/** SystemObject override */
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
@ -46,8 +38,6 @@ class ControllerBase : public HasModesIF,
|
|||||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
void setTaskIF(PeriodicTaskIF *task) override;
|
void setTaskIF(PeriodicTaskIF *task) override;
|
||||||
ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
const HasHealthIF *getOptHealthIF() const override;
|
|
||||||
const HasModesIF &getModeIF() const override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@ -61,11 +51,13 @@ class ControllerBase : public HasModesIF,
|
|||||||
/**
|
/**
|
||||||
* Periodic helper, implemented by child class.
|
* Periodic helper, implemented by child class.
|
||||||
*/
|
*/
|
||||||
virtual void performControlOperation(uint8_t opCode) = 0;
|
virtual void performControlOperation() = 0;
|
||||||
|
|
||||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) override = 0;
|
uint32_t *msToReachTheMode) override = 0;
|
||||||
|
|
||||||
|
const object_id_t parentId;
|
||||||
|
|
||||||
Mode_t mode;
|
Mode_t mode;
|
||||||
|
|
||||||
Submode_t submode;
|
Submode_t submode;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "fsfw/controller/ExtendedControllerBase.h"
|
#include "fsfw/controller/ExtendedControllerBase.h"
|
||||||
|
|
||||||
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
|
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
|
||||||
: ControllerBase(objectId, commandQueueDepth),
|
size_t commandQueueDepth)
|
||||||
|
: ControllerBase(objectId, parentId, commandQueueDepth),
|
||||||
poolManager(this, commandQueue),
|
poolManager(this, commandQueue),
|
||||||
actionHelper(this, commandQueue) {}
|
actionHelper(this, commandQueue) {}
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
|
|||||||
|
|
||||||
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
|
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
|
||||||
handleQueue();
|
handleQueue();
|
||||||
performControlOperation(opCode);
|
performControlOperation();
|
||||||
/* We do this after performing control operation because variables will be set changed
|
/* We do this after performing control operation because variables will be set changed
|
||||||
in this function. */
|
in this function. */
|
||||||
poolManager.performHkOperation();
|
poolManager.performHkOperation();
|
||||||
|
@ -17,7 +17,7 @@ class ExtendedControllerBase : public ControllerBase,
|
|||||||
public HasActionsIF,
|
public HasActionsIF,
|
||||||
public HasLocalDataPoolIF {
|
public HasLocalDataPoolIF {
|
||||||
public:
|
public:
|
||||||
ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3);
|
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
|
||||||
~ExtendedControllerBase() override;
|
~ExtendedControllerBase() override;
|
||||||
|
|
||||||
/* SystemObjectIF overrides */
|
/* SystemObjectIF overrides */
|
||||||
@ -44,9 +44,9 @@ class ExtendedControllerBase : public ControllerBase,
|
|||||||
/**
|
/**
|
||||||
* Periodic helper from ControllerBase, implemented by child class.
|
* Periodic helper from ControllerBase, implemented by child class.
|
||||||
*/
|
*/
|
||||||
void performControlOperation(uint8_t opCode) override = 0;
|
void performControlOperation() override = 0;
|
||||||
|
|
||||||
// Handle the four messages mentioned above
|
/* Handle the four messages mentioned above */
|
||||||
void handleQueue() override;
|
void handleQueue() override;
|
||||||
|
|
||||||
/* HasActionsIF overrides */
|
/* HasActionsIF overrides */
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
#include "fsfw/globalfunctions/constants.h"
|
#include "fsfw/globalfunctions/constants.h"
|
||||||
#include "fsfw/globalfunctions/math/MatrixOperations.h"
|
#include "fsfw/globalfunctions/math/MatrixOperations.h"
|
||||||
#include "fsfw/globalfunctions/math/VectorOperations.h"
|
#include "fsfw/globalfunctions/math/VectorOperations.h"
|
||||||
#include "fsfw/globalfunctions/sign.h"
|
|
||||||
#include "fsfw/serviceinterface.h"
|
|
||||||
|
|
||||||
void CoordinateTransformations::positionEcfToEci(const double* ecfPosition, double* eciPosition,
|
void CoordinateTransformations::positionEcfToEci(const double* ecfPosition, double* eciPosition,
|
||||||
timeval* timeUTC) {
|
timeval* timeUTC) {
|
||||||
@ -99,16 +97,7 @@ void CoordinateTransformations::ecfToEci(const double* ecfCoordinates, double* e
|
|||||||
|
|
||||||
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
|
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
|
||||||
timeval timeTT;
|
timeval timeTT;
|
||||||
ReturnValue_t result = Clock::convertUTCToTT(timeUTC, &timeTT);
|
Clock::convertUTCToTT(timeUTC, &timeTT);
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
// i think it is better to continue here than to abort
|
|
||||||
timeTT = timeUTC;
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "CoordinateTransformations::Conversion from UTC to TT failed. Continuing "
|
|
||||||
"calculations with UTC."
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
double jD2000TT;
|
double jD2000TT;
|
||||||
Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
|
Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
|
||||||
|
|
||||||
@ -218,61 +207,3 @@ void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC, double T
|
|||||||
|
|
||||||
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
|
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
|
||||||
};
|
};
|
||||||
|
|
||||||
void CoordinateTransformations::cartesianFromLatLongAlt(const double lat, const double longi,
|
|
||||||
const double alt, double* cartesianOutput) {
|
|
||||||
/* @brief: cartesianFromLatLongAlt() - calculates cartesian coordinates in ECEF from latitude,
|
|
||||||
* longitude and altitude
|
|
||||||
* @param: lat geodetic latitude [rad]
|
|
||||||
* longi longitude [rad]
|
|
||||||
* alt altitude [m]
|
|
||||||
* cartesianOutput Cartesian Coordinates in ECEF (3x1)
|
|
||||||
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.34ff
|
|
||||||
* Landis Markley and John L. Crassidis*/
|
|
||||||
double radiusPolar = 6356752.314;
|
|
||||||
double radiusEqua = 6378137;
|
|
||||||
|
|
||||||
double eccentricity = sqrt(1 - pow(radiusPolar, 2) / pow(radiusEqua, 2));
|
|
||||||
double auxRadius = radiusEqua / sqrt(1 - pow(eccentricity, 2) * pow(sin(lat), 2));
|
|
||||||
|
|
||||||
cartesianOutput[0] = (auxRadius + alt) * cos(lat) * cos(longi);
|
|
||||||
cartesianOutput[1] = (auxRadius + alt) * cos(lat) * sin(longi);
|
|
||||||
cartesianOutput[2] = ((1 - pow(eccentricity, 2)) * auxRadius + alt) * sin(lat);
|
|
||||||
};
|
|
||||||
|
|
||||||
void CoordinateTransformations::latLongAltFromCartesian(const double* vector, double& latitude,
|
|
||||||
double& longitude, double& altitude) {
|
|
||||||
/* @brief: latLongAltFromCartesian() - calculates latitude, longitude and altitude from
|
|
||||||
* cartesian coordinates in ECEF
|
|
||||||
* @param: x x-value of position vector [m]
|
|
||||||
* y y-value of position vector [m]
|
|
||||||
* z z-value of position vector [m]
|
|
||||||
* latitude geodetic latitude [rad]
|
|
||||||
* longitude longitude [rad]
|
|
||||||
* altitude altitude [m]
|
|
||||||
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.35 f
|
|
||||||
* Landis Markley and John L. Crassidis*/
|
|
||||||
// From World Geodetic System the Earth Radii
|
|
||||||
double a = 6378137.0; // semimajor axis [m]
|
|
||||||
double b = 6356752.3142; // semiminor axis [m]
|
|
||||||
|
|
||||||
// Calculation
|
|
||||||
double e2 = 1 - pow(b, 2) / pow(a, 2);
|
|
||||||
double epsilon2 = pow(a, 2) / pow(b, 2) - 1;
|
|
||||||
double rho = sqrt(pow(vector[0], 2) + pow(vector[1], 2));
|
|
||||||
double p = std::abs(vector[2]) / epsilon2;
|
|
||||||
double s = pow(rho, 2) / (e2 * epsilon2);
|
|
||||||
double q = pow(p, 2) - pow(b, 2) + s;
|
|
||||||
double u = p / sqrt(q);
|
|
||||||
double v = pow(b, 2) * pow(u, 2) / q;
|
|
||||||
double P = 27 * v * s / q;
|
|
||||||
double Q = pow(sqrt(P + 1) + sqrt(P), 2. / 3.);
|
|
||||||
double t = (1 + Q + 1 / Q) / 6;
|
|
||||||
double c = sqrt(pow(u, 2) - 1 + 2 * t);
|
|
||||||
double w = (c - u) / 2;
|
|
||||||
double d = sign(vector[2]) * sqrt(q) * (w + sqrt(sqrt(pow(t, 2) + v) - u * w - t / 2 - 1. / 4.));
|
|
||||||
double N = a * sqrt(1 + epsilon2 * pow(d, 2) / pow(b, 2));
|
|
||||||
latitude = asin((epsilon2 + 1) * d / N);
|
|
||||||
altitude = rho * cos(latitude) + vector[2] * sin(latitude) - pow(a, 2) / N;
|
|
||||||
longitude = atan2(vector[1], vector[0]);
|
|
||||||
}
|
|
||||||
|
@ -23,12 +23,6 @@ class CoordinateTransformations {
|
|||||||
|
|
||||||
static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]);
|
static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]);
|
||||||
|
|
||||||
static void cartesianFromLatLongAlt(const double lat, const double longi, const double alt,
|
|
||||||
double* cartesianOutput);
|
|
||||||
|
|
||||||
static void latLongAltFromCartesian(const double* vector, double& latitude, double& longitude,
|
|
||||||
double& altitude);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CoordinateTransformations();
|
CoordinateTransformations();
|
||||||
static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,
|
static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,
|
||||||
|
@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
|
|||||||
timeval timeSinceEpoch = time - epoch;
|
timeval timeSinceEpoch = time - epoch;
|
||||||
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
|
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
|
||||||
|
|
||||||
double daysSinceEpoch = minutesSinceEpoch / 60 / 24;
|
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
|
||||||
|
|
||||||
if ((daysSinceEpoch > 7) || (daysSinceEpoch < -7)) {
|
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
|
||||||
return TLE_TOO_OLD;
|
return TLE_TOO_OLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,18 +88,13 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets(TcTransferFrame* frame)
|
|||||||
uint32_t totalLength = frame->getDataLength();
|
uint32_t totalLength = frame->getDataLength();
|
||||||
if (totalLength > MAX_PACKET_SIZE) return CONTENT_TOO_LARGE;
|
if (totalLength > MAX_PACKET_SIZE) return CONTENT_TOO_LARGE;
|
||||||
uint8_t* position = frame->getDataField();
|
uint8_t* position = frame->getDataField();
|
||||||
while ((totalLength > ccsds::HEADER_LEN)) {
|
while ((totalLength > SpacePacketBase::MINIMUM_SIZE)) {
|
||||||
SpacePacketReader packet(position, totalLength);
|
SpacePacketBase packet(position);
|
||||||
status = packet.checkSize();
|
uint32_t packetSize = packet.getFullSize();
|
||||||
if (status != returnvalue::OK) {
|
|
||||||
// TODO: Better error handling
|
|
||||||
status = DATA_CORRUPTED;
|
|
||||||
}
|
|
||||||
uint32_t packetSize = packet.getFullPacketLen();
|
|
||||||
if (packetSize <= totalLength) {
|
if (packetSize <= totalLength) {
|
||||||
status = sendCompletePacket(packet.getFullData(), packet.getFullPacketLen());
|
status = sendCompletePacket(packet.getWholeData(), packet.getFullSize());
|
||||||
totalLength -= packet.getFullPacketLen();
|
totalLength -= packet.getFullSize();
|
||||||
position += packet.getFullPacketLen();
|
position += packet.getFullSize();
|
||||||
status = returnvalue::OK;
|
status = returnvalue::OK;
|
||||||
} else {
|
} else {
|
||||||
status = DATA_CORRUPTED;
|
status = DATA_CORRUPTED;
|
||||||
@ -112,7 +107,7 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets(TcTransferFrame* frame)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MapPacketExtraction::sendCompletePacket(const uint8_t* data, uint32_t size) {
|
ReturnValue_t MapPacketExtraction::sendCompletePacket(uint8_t* data, uint32_t size) {
|
||||||
store_address_t store_id;
|
store_address_t store_id;
|
||||||
ReturnValue_t status = this->packetStore->addData(&store_id, data, size);
|
ReturnValue_t status = this->packetStore->addData(&store_id, data, size);
|
||||||
if (status == returnvalue::OK) {
|
if (status == returnvalue::OK) {
|
||||||
|
@ -47,7 +47,7 @@ class MapPacketExtraction : public MapPacketExtractionIF {
|
|||||||
* @param size Complete total size of the packet.
|
* @param size Complete total size of the packet.
|
||||||
* @return Return Code of the Packet Store or the Message Queue.
|
* @return Return Code of the Packet Store or the Message Queue.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t sendCompletePacket(const uint8_t* data, uint32_t size);
|
ReturnValue_t sendCompletePacket(uint8_t* data, uint32_t size);
|
||||||
/**
|
/**
|
||||||
* Helper method to reset the internal buffer.
|
* Helper method to reset the internal buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -64,8 +64,8 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
|
|||||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||||
* commit() in between
|
* commit() in between
|
||||||
*/
|
*/
|
||||||
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
uint32_t lockTimeout = 20) override;
|
uint32_t lockTimeout = 20) override;
|
||||||
/**
|
/**
|
||||||
* @brief The commit call initializes writing back the registered variables.
|
* @brief The commit call initializes writing back the registered variables.
|
||||||
* @details
|
* @details
|
||||||
@ -84,15 +84,15 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
|
|||||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||||
* contains non write-only variables
|
* contains non write-only variables
|
||||||
*/
|
*/
|
||||||
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
uint32_t lockTimeout = 20) override;
|
uint32_t lockTimeout = 20) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the passed pool variable instance into the data set.
|
* Register the passed pool variable instance into the data set.
|
||||||
* @param variable
|
* @param variable
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t registerVariable(PoolVariableIF* variable) override;
|
virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the means to lock the underlying data structure to ensure
|
* Provides the means to lock the underlying data structure to ensure
|
||||||
|
@ -70,7 +70,8 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() {
|
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) {
|
||||||
|
setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
|
||||||
return initializeHousekeepingPoolEntriesOnce();
|
return initializeHousekeepingPoolEntriesOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +286,6 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(HousekeepingSnapshot& updat
|
|||||||
result = updatePacket.serialize(&storePtr, &serializedSize, updatePacketSize,
|
result = updatePacket.serialize(&storePtr, &serializedSize, updatePacketSize,
|
||||||
SerializeIF::Endianness::MACHINE);
|
SerializeIF::Endianness::MACHINE);
|
||||||
return result;
|
return result;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId,
|
void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId,
|
||||||
@ -349,6 +349,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(subdp::ParamsBase
|
|||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
|
||||||
if (dataSet != nullptr) {
|
if (dataSet != nullptr) {
|
||||||
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting);
|
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting);
|
||||||
|
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics());
|
||||||
LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval,
|
LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval,
|
||||||
owner->getPeriodicOperationFrequency());
|
owner->getPeriodicOperationFrequency());
|
||||||
}
|
}
|
||||||
@ -380,6 +381,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(subdp::ParamsBase&
|
|||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
|
||||||
if (dataSet != nullptr) {
|
if (dataSet != nullptr) {
|
||||||
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true);
|
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true);
|
||||||
|
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics());
|
||||||
}
|
}
|
||||||
|
|
||||||
hkReceivers.push_back(hkReceiver);
|
hkReceivers.push_back(hkReceiver);
|
||||||
@ -463,37 +465,70 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
|
|||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
switch (command) {
|
switch (command) {
|
||||||
// Houskeeping interface handling.
|
// Houskeeping interface handling.
|
||||||
|
case (HousekeepingMessage::ENABLE_PERIODIC_DIAGNOSTICS_GENERATION): {
|
||||||
|
result = togglePeriodicGeneration(sid, true, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case (HousekeepingMessage::DISABLE_PERIODIC_DIAGNOSTICS_GENERATION): {
|
||||||
|
result = togglePeriodicGeneration(sid, false, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case (HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): {
|
case (HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): {
|
||||||
result = togglePeriodicGeneration(sid, true);
|
result = togglePeriodicGeneration(sid, true, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case (HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): {
|
case (HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): {
|
||||||
result = togglePeriodicGeneration(sid, false);
|
result = togglePeriodicGeneration(sid, false, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case (HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): {
|
case (HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): {
|
||||||
result = generateSetStructurePacket(sid);
|
result = generateSetStructurePacket(sid, true);
|
||||||
if (result == returnvalue::OK) {
|
if (result == returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case (HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): {
|
||||||
|
result = generateSetStructurePacket(sid, false);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL):
|
||||||
case (HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
|
case (HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
|
||||||
float newCollIntvl = 0;
|
float newCollIntvl = 0;
|
||||||
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
|
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
|
||||||
result = changeCollectionInterval(sid, newCollIntvl);
|
if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
|
||||||
|
result = changeCollectionInterval(sid, newCollIntvl, true);
|
||||||
|
} else {
|
||||||
|
result = changeCollectionInterval(sid, newCollIntvl, false);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): {
|
case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT):
|
||||||
|
case (HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): {
|
||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||||
if (dataSet == nullptr) {
|
if (dataSet == nullptr) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
|
||||||
DATASET_NOT_FOUND);
|
DATASET_NOT_FOUND);
|
||||||
return DATASET_NOT_FOUND;
|
return DATASET_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
if (command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT and
|
||||||
|
LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
|
||||||
|
result = WRONG_HK_PACKET_TYPE;
|
||||||
|
break;
|
||||||
|
} else if (command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT and
|
||||||
|
not LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
|
||||||
|
result = WRONG_HK_PACKET_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return generateHousekeepingPacket(HousekeepingMessage::getSid(message), dataSet, true);
|
return generateHousekeepingPacket(HousekeepingMessage::getSid(message), dataSet, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,10 +569,6 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
|
|||||||
|
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
if (result == WRONG_HK_PACKET_TYPE) {
|
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
|
|
||||||
WRONG_HK_PACKET_TYPE);
|
|
||||||
}
|
|
||||||
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
|
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
|
||||||
} else {
|
} else {
|
||||||
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
|
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
|
||||||
@ -583,7 +614,11 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
|
|||||||
|
|
||||||
/* Now we set a HK message and send it the HK packet destination. */
|
/* Now we set a HK message and send it the HK packet destination. */
|
||||||
CommandMessage hkMessage;
|
CommandMessage hkMessage;
|
||||||
HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId);
|
if (LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
|
||||||
|
HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId);
|
||||||
|
} else {
|
||||||
|
HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId);
|
||||||
|
}
|
||||||
|
|
||||||
if (hkQueue == nullptr) {
|
if (hkQueue == nullptr) {
|
||||||
/* Error, no queue available to send packet with. */
|
/* Error, no queue available to send packet with. */
|
||||||
@ -621,6 +656,10 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacke
|
|||||||
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE);
|
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalDataPoolManager::setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor) {
|
||||||
|
this->nonDiagnosticIntervalFactor = nonDiagInvlFactor;
|
||||||
|
}
|
||||||
|
|
||||||
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||||
sid_t sid = receiver.dataId.sid;
|
sid_t sid = receiver.dataId.sid;
|
||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||||
@ -658,7 +697,8 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool enable) {
|
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool enable,
|
||||||
|
bool isDiagnostics) {
|
||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||||
if (dataSet == nullptr) {
|
if (dataSet == nullptr) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "togglePeriodicGeneration",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "togglePeriodicGeneration",
|
||||||
@ -666,17 +706,22 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena
|
|||||||
return DATASET_NOT_FOUND;
|
return DATASET_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and not isDiagnostics) or
|
||||||
|
(not LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and isDiagnostics)) {
|
||||||
|
return WRONG_HK_PACKET_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
|
if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
|
||||||
(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
|
(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
|
||||||
return returnvalue::OK;
|
return REPORTING_STATUS_UNCHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
|
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
|
||||||
float newCollectionInterval) {
|
bool isDiagnostics) {
|
||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||||
if (dataSet == nullptr) {
|
if (dataSet == nullptr) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
|
||||||
@ -684,6 +729,11 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
|||||||
return DATASET_NOT_FOUND;
|
return DATASET_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
|
||||||
|
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
|
||||||
|
return WRONG_HK_PACKET_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
PeriodicHousekeepingHelper* periodicHelper =
|
PeriodicHousekeepingHelper* periodicHelper =
|
||||||
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
|
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
|
||||||
|
|
||||||
@ -696,7 +746,7 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
|
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool isDiagnostics) {
|
||||||
/* Get and check dataset first. */
|
/* Get and check dataset first. */
|
||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||||
if (dataSet == nullptr) {
|
if (dataSet == nullptr) {
|
||||||
@ -705,6 +755,11 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
|
|||||||
return DATASET_NOT_FOUND;
|
return DATASET_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
|
||||||
|
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
|
||||||
|
return WRONG_HK_PACKET_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
bool valid = dataSet->isValid();
|
bool valid = dataSet->isValid();
|
||||||
bool reportingEnabled = LocalPoolDataSetAttorney::getReportingEnabled(*dataSet);
|
bool reportingEnabled = LocalPoolDataSetAttorney::getReportingEnabled(*dataSet);
|
||||||
float collectionInterval =
|
float collectionInterval =
|
||||||
@ -736,7 +791,11 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
|
|||||||
|
|
||||||
// Send structure reporting reply.
|
// Send structure reporting reply.
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
|
if (isDiagnostics) {
|
||||||
|
HousekeepingMessage::setDiagnosticsStuctureReportReply(&reply, sid, storeId);
|
||||||
|
} else {
|
||||||
|
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
|
||||||
|
}
|
||||||
|
|
||||||
result = hkQueue->reply(&reply);
|
result = hkQueue->reply(&reply);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
@ -765,8 +824,6 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
|||||||
errorPrint = "Dataset not found";
|
errorPrint = "Dataset not found";
|
||||||
} else if (error == POOLOBJECT_NOT_FOUND) {
|
} else if (error == POOLOBJECT_NOT_FOUND) {
|
||||||
errorPrint = "Pool Object not found";
|
errorPrint = "Pool Object not found";
|
||||||
} else if (error == WRONG_HK_PACKET_TYPE) {
|
|
||||||
errorPrint = "Wrong Packet Type";
|
|
||||||
} else if (error == returnvalue::FAILED) {
|
} else if (error == returnvalue::FAILED) {
|
||||||
if (outputType == sif::OutputTypes::OUT_WARNING) {
|
if (outputType == sif::OutputTypes::OUT_WARNING) {
|
||||||
errorPrint = "Generic Warning";
|
errorPrint = "Generic Warning";
|
||||||
|
@ -102,7 +102,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
|||||||
* @param nonDiagInvlFactor
|
* @param nonDiagInvlFactor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initializeAfterTaskCreation();
|
ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This should be called in the periodic handler of the owner.
|
* @brief This should be called in the periodic handler of the owner.
|
||||||
@ -152,6 +152,17 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
|||||||
MessageQueueId_t targetQueueId,
|
MessageQueueId_t targetQueueId,
|
||||||
bool generateSnapshot) override;
|
bool generateSnapshot) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||||
|
* than diagnostic packets.
|
||||||
|
* A factor can be specified to determine the minimum sampling frequency
|
||||||
|
* for non-diagnostic packets. The minimum sampling frequency of the
|
||||||
|
* diagnostics packets,which is usually jusst the period of the
|
||||||
|
* performOperation calls, is multiplied with that factor.
|
||||||
|
* @param factor
|
||||||
|
*/
|
||||||
|
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The manager is also able to handle housekeeping messages.
|
* @brief The manager is also able to handle housekeeping messages.
|
||||||
* @details
|
* @details
|
||||||
@ -174,7 +185,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
|||||||
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
|
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
|
||||||
bool forDownlink,
|
bool forDownlink,
|
||||||
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
||||||
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
|
|
||||||
|
|
||||||
HasLocalDataPoolIF* getOwner();
|
HasLocalDataPoolIF* getOwner();
|
||||||
|
|
||||||
@ -337,8 +347,10 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
|||||||
size_t* serializedSize);
|
size_t* serializedSize);
|
||||||
|
|
||||||
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
||||||
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable);
|
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
|
||||||
ReturnValue_t generateSetStructurePacket(sid_t sid);
|
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
|
||||||
|
bool isDiagnostics);
|
||||||
|
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
||||||
|
|
||||||
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
||||||
void handleChangeResetLogic(DataType type, DataId dataId, MarkChangedIF* toReset);
|
void handleChangeResetLogic(DataType type, DataId dataId, MarkChangedIF* toReset);
|
||||||
@ -352,6 +364,10 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
|||||||
void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
|
void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
|
||||||
ReturnValue_t errorCode = returnvalue::FAILED,
|
ReturnValue_t errorCode = returnvalue::FAILED,
|
||||||
const char* errorPrint = nullptr);
|
const char* errorPrint = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using ProvidesDataPoolSubscriptionIF::subscribeForPeriodicPacket;
|
||||||
|
using ProvidesDataPoolSubscriptionIF::subscribeForUpdatePacket;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -239,6 +239,10 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, si
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) { this->diagnostic = isDiagnostics; }
|
||||||
|
|
||||||
|
bool LocalPoolDataSetBase::isDiagnostics() const { return diagnostic; }
|
||||||
|
|
||||||
void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
|
void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
|
||||||
this->reportingEnabled = reportingEnabled;
|
this->reportingEnabled = reportingEnabled;
|
||||||
}
|
}
|
||||||
@ -246,8 +250,9 @@ void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
|
|||||||
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
|
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
|
||||||
|
|
||||||
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
|
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
|
||||||
dur_millis_t minimumPeriodicInterval) {
|
dur_millis_t minimumPeriodicInterval,
|
||||||
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval);
|
uint8_t nonDiagIntervalFactor) {
|
||||||
|
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }
|
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }
|
||||||
|
@ -162,7 +162,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
|
|||||||
object_id_t getCreatorObjectId();
|
object_id_t getCreatorObjectId();
|
||||||
|
|
||||||
bool getReportingEnabled() const;
|
bool getReportingEnabled() const;
|
||||||
void setReportingEnabled(bool enabled);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current periodic HK generation interval this set
|
* Returns the current periodic HK generation interval this set
|
||||||
@ -182,12 +181,18 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
|
|||||||
//! This mutex is used if the data is created by one object only.
|
//! This mutex is used if the data is created by one object only.
|
||||||
MutexIF* mutexIfSingleDataCreator = nullptr;
|
MutexIF* mutexIfSingleDataCreator = nullptr;
|
||||||
|
|
||||||
|
bool diagnostic = false;
|
||||||
|
void setDiagnostic(bool diagnostics);
|
||||||
|
bool isDiagnostics() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for periodic generation.
|
* Used for periodic generation.
|
||||||
*/
|
*/
|
||||||
bool reportingEnabled = false;
|
bool reportingEnabled = false;
|
||||||
|
void setReportingEnabled(bool enabled);
|
||||||
|
|
||||||
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval);
|
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
||||||
|
uint8_t nonDiagIntervalFactor = 5);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the valid state of a dataset is always relevant to the whole
|
* If the valid state of a dataset is always relevant to the whole
|
||||||
|
@ -87,9 +87,9 @@ class LocalPoolVariable : public LocalPoolObjectBase {
|
|||||||
|
|
||||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
SerializeIF::Endianness streamEndianness) const override;
|
SerializeIF::Endianness streamEndianness) const override;
|
||||||
size_t getSerializedSize() const override;
|
virtual size_t getSerializedSize() const override;
|
||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
SerializeIF::Endianness streamEndianness) override;
|
SerializeIF::Endianness streamEndianness) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is a call to read the array's values
|
* @brief This is a call to read the array's values
|
||||||
|
@ -98,11 +98,11 @@ class LocalPoolVector : public LocalPoolObjectBase {
|
|||||||
T& operator[](size_t i);
|
T& operator[](size_t i);
|
||||||
const T& operator[](size_t i) const;
|
const T& operator[](size_t i) const;
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
||||||
SerializeIF::Endianness streamEndiannes) const override;
|
SerializeIF::Endianness streamEndiannes) const override;
|
||||||
size_t getSerializedSize() const override;
|
virtual size_t getSerializedSize() const override;
|
||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
SerializeIF::Endianness streamEndianness) override;
|
SerializeIF::Endianness streamEndianness) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is a call to read the array's values
|
* @brief This is a call to read the array's values
|
||||||
|
@ -98,6 +98,11 @@ class ProvidesDataPoolSubscriptionIF {
|
|||||||
virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0;
|
virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0;
|
||||||
virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0;
|
virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0;
|
||||||
|
|
||||||
|
// virtual ReturnValue_t
|
||||||
|
// subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, bool isDiagnostics) {
|
||||||
|
// return subscribeForUpdatePacket(sid, reportingEnabled, isDiagnostics, objects::NO_OBJECT);
|
||||||
|
// }
|
||||||
|
|
||||||
[[deprecated(
|
[[deprecated(
|
||||||
"Please use the new API which takes all arguments as one wrapper "
|
"Please use the new API which takes all arguments as one wrapper "
|
||||||
"struct")]] virtual ReturnValue_t
|
"struct")]] virtual ReturnValue_t
|
||||||
|
@ -5,9 +5,17 @@
|
|||||||
|
|
||||||
class LocalPoolDataSetAttorney {
|
class LocalPoolDataSetAttorney {
|
||||||
private:
|
private:
|
||||||
|
static void setDiagnostic(LocalPoolDataSetBase& set, bool diagnostics) {
|
||||||
|
set.setDiagnostic(diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isDiagnostics(LocalPoolDataSetBase& set) { return set.isDiagnostics(); }
|
||||||
|
|
||||||
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
|
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
|
||||||
uint32_t minimumPeriodicIntervalMs) {
|
uint32_t minimumPeriodicIntervalMs,
|
||||||
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs);
|
uint8_t nonDiagIntervalFactor = 5) {
|
||||||
|
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs,
|
||||||
|
nonDiagIntervalFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {
|
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "fsfw/devicehandlers/AssemblyBase.h"
|
#include "fsfw/devicehandlers/AssemblyBase.h"
|
||||||
|
|
||||||
AssemblyBase::AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth)
|
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth)
|
||||||
: SubsystemBase(objectId, MODE_OFF, commandQueueDepth),
|
: SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
|
||||||
internalState(STATE_NONE),
|
internalState(STATE_NONE),
|
||||||
recoveryState(RECOVERY_IDLE),
|
recoveryState(RECOVERY_IDLE),
|
||||||
recoveringDevice(childrenMap.end()),
|
recoveringDevice(childrenMap.end()),
|
||||||
@ -26,7 +26,11 @@ void AssemblyBase::performChildOperation() {
|
|||||||
|
|
||||||
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||||
doStartTransition(mode, submode);
|
doStartTransition(mode, submode);
|
||||||
triggerModeHelperEvents(mode, submode);
|
if (modeHelper.isForced()) {
|
||||||
|
triggerEvent(FORCING_MODE, mode, submode);
|
||||||
|
} else {
|
||||||
|
triggerEvent(CHANGING_MODE, mode, submode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
||||||
@ -73,10 +77,9 @@ bool AssemblyBase::handleChildrenChangedHealth() {
|
|||||||
}
|
}
|
||||||
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
||||||
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
||||||
triggerEvent(TRYING_RECOVERY, iter->first, 0);
|
triggerEvent(TRYING_RECOVERY);
|
||||||
recoveryState = RECOVERY_STARTED;
|
recoveryState = RECOVERY_STARTED;
|
||||||
recoveringDevice = iter;
|
recoveringDevice = iter;
|
||||||
// The user needs to take care of commanding the children off in commandChildren
|
|
||||||
doStartTransition(targetMode, targetSubmode);
|
doStartTransition(targetMode, targetSubmode);
|
||||||
} else {
|
} else {
|
||||||
triggerEvent(CHILD_CHANGED_HEALTH);
|
triggerEvent(CHILD_CHANGED_HEALTH);
|
||||||
@ -225,9 +228,6 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
|
|||||||
bool AssemblyBase::checkAndHandleRecovery() {
|
bool AssemblyBase::checkAndHandleRecovery() {
|
||||||
switch (recoveryState) {
|
switch (recoveryState) {
|
||||||
case RECOVERY_STARTED:
|
case RECOVERY_STARTED:
|
||||||
// The recovery was already start in #handleChildrenChangedHealth and we just need
|
|
||||||
// to wait for an off time period.
|
|
||||||
// TODO: make time period configurable
|
|
||||||
recoveryState = RECOVERY_WAIT;
|
recoveryState = RECOVERY_WAIT;
|
||||||
recoveryOffTimer.resetTimer();
|
recoveryOffTimer.resetTimer();
|
||||||
return true;
|
return true;
|
||||||
@ -266,11 +266,3 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
|
|||||||
modeHelper.setForced(true);
|
modeHelper.setForced(true);
|
||||||
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
|
|
||||||
if (modeHelper.isForced()) {
|
|
||||||
triggerEvent(FORCING_MODE, mode, submode);
|
|
||||||
} else {
|
|
||||||
triggerEvent(CHANGING_MODE, mode, submode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
* Documentation: Dissertation Baetz p.156, 157.
|
* Documentation: Dissertation Baetz p.156, 157.
|
||||||
*
|
*
|
||||||
* This class reduces the complexity of controller components which would
|
* This class reduces the complexity of controller components which would
|
||||||
* otherwise be needed for the handling of redundant devices. However, it can also be used to
|
* otherwise be needed for the handling of redundant devices.
|
||||||
* manage the mode keeping and recovery of non-redundant devices
|
|
||||||
*
|
*
|
||||||
* The template class monitors mode and health state of its children
|
* The template class monitors mode and health state of its children
|
||||||
* and checks availability of devices on every detected change.
|
* and checks availability of devices on every detected change.
|
||||||
@ -27,9 +26,11 @@
|
|||||||
*
|
*
|
||||||
* Important:
|
* Important:
|
||||||
*
|
*
|
||||||
* The implementation must call #registerChild for all commanded children during initialization.
|
* The implementation must call registerChild(object_id_t child)
|
||||||
|
* for all commanded children during initialization.
|
||||||
* The implementation must call the initialization function of the base class.
|
* The implementation must call the initialization function of the base class.
|
||||||
* (This will call the function in SubsystemBase)
|
* (This will call the function in SubsystemBase)
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class AssemblyBase : public SubsystemBase {
|
class AssemblyBase : public SubsystemBase {
|
||||||
public:
|
public:
|
||||||
@ -41,15 +42,14 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
|
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
|
||||||
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
|
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
|
||||||
|
|
||||||
AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth = 8);
|
AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth = 8);
|
||||||
virtual ~AssemblyBase();
|
virtual ~AssemblyBase();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Command children to reach [mode,submode] combination. Can be done by setting
|
* Command children to reach [mode,submode] combination
|
||||||
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
|
* Can be done by setting #commandsOutstanding correctly,
|
||||||
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
|
* or using executeTable()
|
||||||
* a recovery might be on-going and the device needs to be commanded to off first.
|
|
||||||
* @param mode
|
* @param mode
|
||||||
* @param submode
|
* @param submode
|
||||||
* @return
|
* @return
|
||||||
@ -120,19 +120,8 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
||||||
|
|
||||||
/**
|
virtual void performChildOperation();
|
||||||
* @brief Default periodic handler
|
|
||||||
* @details
|
|
||||||
* This is the default periodic handler which will be called by the SubsystemBase
|
|
||||||
* performOperation. It performs the child transitions or reacts to changed health/mode states
|
|
||||||
* of children objects
|
|
||||||
*/
|
|
||||||
virtual void performChildOperation() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function handles changed mode or health states of children
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool handleChildrenChanged();
|
bool handleChildrenChanged();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,37 +134,12 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
bool handleChildrenChangedHealth();
|
bool handleChildrenChangedHealth();
|
||||||
|
|
||||||
/**
|
|
||||||
* Core transition handler. The default implementation will only do something if
|
|
||||||
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
|
|
||||||
* from the #doPerformTransition call were executed successfully.
|
|
||||||
*
|
|
||||||
* Unless a second step was requested, the function will then use #checkChildrenState to
|
|
||||||
* determine whether the target mode was reached.
|
|
||||||
*
|
|
||||||
* There is some special handling for certain (internal) modes:
|
|
||||||
* - A second step is necessary. #commandChildren will be performed again
|
|
||||||
* - The device health was overwritten. #commandChildren will be called
|
|
||||||
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
|
|
||||||
*/
|
|
||||||
virtual void handleChildrenTransition();
|
virtual void handleChildrenTransition();
|
||||||
|
|
||||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
|
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls #doStartTransition and triggers an informative event as well that the mode will
|
|
||||||
* change
|
|
||||||
* @param mode
|
|
||||||
* @param submode
|
|
||||||
*/
|
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||||
|
|
||||||
/**
|
|
||||||
* This function starts the transition by setting the internal #targetSubmode and #targetMode
|
|
||||||
* variables and then calling the #commandChildren function.
|
|
||||||
* @param mode
|
|
||||||
* @param submode
|
|
||||||
*/
|
|
||||||
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
||||||
|
|
||||||
virtual bool isInTransition();
|
virtual bool isInTransition();
|
||||||
@ -196,7 +160,7 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
* Manages recovery of a device
|
* Manages recovery of a device
|
||||||
* @return true if recovery is still ongoing, false else.
|
* @return true if recovery is still ongoing, false else.
|
||||||
*/
|
*/
|
||||||
virtual bool checkAndHandleRecovery();
|
bool checkAndHandleRecovery();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to overwrite health state of one of the children.
|
* Helper method to overwrite health state of one of the children.
|
||||||
@ -204,8 +168,6 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
* @param objectId Must be a registered child.
|
* @param objectId Must be a registered child.
|
||||||
*/
|
*/
|
||||||
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
||||||
|
|
||||||
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
||||||
|
@ -7,5 +7,4 @@ target_sources(
|
|||||||
DeviceHandlerFailureIsolation.cpp
|
DeviceHandlerFailureIsolation.cpp
|
||||||
DeviceHandlerMessage.cpp
|
DeviceHandlerMessage.cpp
|
||||||
DeviceTmReportingWrapper.cpp
|
DeviceTmReportingWrapper.cpp
|
||||||
FreshDeviceHandlerBase.cpp
|
|
||||||
HealthDevice.cpp)
|
HealthDevice.cpp)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user