Merge branch 'development' into mohr/timetag_fix
This commit is contained in:
commit
877c5fa798
126
CHANGELOG.md
126
CHANGELOG.md
@ -8,26 +8,48 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
# [v6.0.0]
|
## Fixes
|
||||||
|
|
||||||
|
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
|
||||||
|
- PUS Health Service: Size check for set health command.
|
||||||
|
- PUS Health Service: Perform operation completion for announce health command.
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Assert that `FixedArrayList` is larger than 0 at compile time.
|
||||||
|
|
||||||
|
# [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
|
||||||
- Bugfix for RM3100 MGM sensors. Z value was previously calculated
|
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
|
||||||
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/files
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710
|
||||||
- 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
|
||||||
@ -37,6 +59,36 @@ 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
|
||||||
|
|
||||||
@ -53,13 +105,36 @@ 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
|
||||||
to they can be used without template specification.
|
so 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
|
||||||
@ -89,18 +164,41 @@ 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
|
||||||
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
- Generic TMTC Bridge Update
|
||||||
interface itself so it can be re-used more easily. Also add new
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
|
||||||
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
- comment tweak to event parser can read everything
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
|
||||||
|
- 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
|
||||||
|
|
||||||
@ -120,7 +218,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] 25.07.2022
|
# [v5.0.0] 2022-07-25
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
|
|||||||
# Version file handling #
|
# Version file handling #
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
|
|
||||||
set(FSFW_VERSION_IF_GIT_FAILS 5)
|
set(FSFW_VERSION_IF_GIT_FAILS 6)
|
||||||
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)
|
||||||
|
|
||||||
@ -153,12 +153,12 @@ if(FSFW_BUILD_TESTS)
|
|||||||
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
||||||
)
|
)
|
||||||
# Check whether the user has already installed Catch2 first
|
# Check whether the user has already installed Catch2 first
|
||||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET)
|
||||||
# Not installed, so use FetchContent to download and provide Catch2
|
# Not installed, so use FetchContent to download and provide Catch2
|
||||||
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)
|
||||||
|
|
||||||
@ -201,8 +201,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} No ETL installation was found with find_package. Installing and providing "
|
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
|
||||||
"etl with FindPackage")
|
)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
|
110
scripts/check_release.py
Executable file
110
scripts/check_release.py
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
#! /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()
|
@ -12,6 +12,7 @@ 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];
|
||||||
|
@ -33,6 +33,7 @@ enum : uint8_t {
|
|||||||
PUS_SERVICE_23 = 103,
|
PUS_SERVICE_23 = 103,
|
||||||
MGM_LIS3MDL = 106,
|
MGM_LIS3MDL = 106,
|
||||||
MGM_RM3100 = 107,
|
MGM_RM3100 = 107,
|
||||||
|
CFDP = 108,
|
||||||
|
|
||||||
FW_SUBSYSTEM_ID_RANGE
|
FW_SUBSYSTEM_ID_RANGE
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "HealthTableIF.h"
|
#include "HealthTableIF.h"
|
||||||
|
|
||||||
class HealthTable : public HealthTableIF, public SystemObject {
|
class HealthTable : public HealthTableIF, public SystemObject {
|
||||||
|
friend class CServiceHealthCommanding;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HealthTable(object_id_t objectid);
|
explicit HealthTable(object_id_t objectid);
|
||||||
~HealthTable() override;
|
~HealthTable() override;
|
||||||
|
@ -24,3 +24,19 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason
|
|||||||
message->setParameter(reason);
|
message->setParameter(reason);
|
||||||
message->setParameter2(0);
|
message->setParameter2(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive) {
|
||||||
|
Command_t cmd;
|
||||||
|
if (recursive) {
|
||||||
|
cmd = CMD_MODE_ANNOUNCE_RECURSIVELY;
|
||||||
|
} else {
|
||||||
|
cmd = CMD_MODE_ANNOUNCE;
|
||||||
|
}
|
||||||
|
message.setCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModeMessage::setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode) {
|
||||||
|
setModeMessage(&message, CMD_MODE_COMMAND, mode, submode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModeMessage::setModeReadMessage(CommandMessage& message) { message.setCommand(CMD_MODE_READ); }
|
||||||
|
@ -45,6 +45,9 @@ class ModeMessage {
|
|||||||
|
|
||||||
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
|
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
|
||||||
Submode_t submode);
|
Submode_t submode);
|
||||||
|
static void setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode);
|
||||||
|
static void setModeAnnounceMessage(CommandMessage& message, bool recursive);
|
||||||
|
static void setModeReadMessage(CommandMessage& message);
|
||||||
static void setCantReachMode(CommandMessage* message, ReturnValue_t reason);
|
static void setCantReachMode(CommandMessage* message, ReturnValue_t reason);
|
||||||
static void clear(CommandMessage* message);
|
static void clear(CommandMessage* message);
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,10 @@ elseif(FSFW_OSAL MATCHES "host")
|
|||||||
endif()
|
endif()
|
||||||
set(FSFW_OSAL_HOST 1)
|
set(FSFW_OSAL_HOST 1)
|
||||||
else()
|
else()
|
||||||
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
|
message(
|
||||||
|
WARNING
|
||||||
|
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
|
||||||
|
|
||||||
# Not set. Assumuing this is a host build, try to determine host OS
|
# Not set. Assumuing this is a host build, try to determine host OS
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_subdirectory(host)
|
add_subdirectory(host)
|
||||||
|
@ -78,7 +78,6 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
* https://man7.org/linux/man-pages/man7/socket.7.html for more details.
|
* https://man7.org/linux/man-pages/man7/socket.7.html for more details.
|
||||||
*/
|
*/
|
||||||
bool reusePort = false;
|
bool reusePort = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
enum class ReceptionModes { SPACE_PACKETS };
|
enum class ReceptionModes { SPACE_PACKETS };
|
||||||
|
|
||||||
|
@ -76,15 +76,18 @@ timeval Clock::getUptime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
||||||
// TODO This is not posix compatible and delivers only seconds precision
|
|
||||||
// Linux specific file read but more precise.
|
|
||||||
double uptimeSeconds;
|
double uptimeSeconds;
|
||||||
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
|
std::ifstream ifile("/proc/uptime");
|
||||||
|
if (ifile.bad()) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
if (ifile >> uptimeSeconds) {
|
||||||
uptime->tv_sec = uptimeSeconds;
|
uptime->tv_sec = uptimeSeconds;
|
||||||
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
|
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
|
||||||
}
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for new FSFW Clock function delivering seconds uptime.
|
// Wait for new FSFW Clock function delivering seconds uptime.
|
||||||
// uint32_t Clock::getUptimeSeconds() {
|
// uint32_t Clock::getUptimeSeconds() {
|
||||||
|
@ -9,4 +9,4 @@ target_sources(
|
|||||||
Service17Test.cpp
|
Service17Test.cpp
|
||||||
Service20ParameterManagement.cpp
|
Service20ParameterManagement.cpp
|
||||||
CService200ModeCommanding.cpp
|
CService200ModeCommanding.cpp
|
||||||
CService201HealthCommanding.cpp)
|
CServiceHealthCommanding.cpp)
|
||||||
|
@ -19,7 +19,8 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
|
|||||||
switch (subservice) {
|
switch (subservice) {
|
||||||
case (Subservice::COMMAND_MODE_COMMAND):
|
case (Subservice::COMMAND_MODE_COMMAND):
|
||||||
case (Subservice::COMMAND_MODE_READ):
|
case (Subservice::COMMAND_MODE_READ):
|
||||||
case (Subservice::COMMAND_MODE_ANNCOUNCE):
|
case (Subservice::COMMAND_MODE_ANNOUNCE):
|
||||||
|
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
default:
|
default:
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
@ -53,6 +54,9 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
|
|||||||
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
||||||
const uint8_t *tcData, size_t tcDataLen,
|
const uint8_t *tcData, size_t tcDataLen,
|
||||||
uint32_t *state, object_id_t objectId) {
|
uint32_t *state, object_id_t objectId) {
|
||||||
|
bool recursive = false;
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_MODE_COMMAND): {
|
||||||
ModePacket modeCommandPacket;
|
ModePacket modeCommandPacket;
|
||||||
ReturnValue_t result =
|
ReturnValue_t result =
|
||||||
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
@ -60,9 +64,22 @@ ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
|
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND,
|
||||||
modeCommandPacket.getSubmode());
|
modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
|
||||||
return result;
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
|
||||||
|
recursive = true;
|
||||||
|
[[fallthrough]];
|
||||||
|
case (Subservice::COMMAND_MODE_ANNOUNCE):
|
||||||
|
ModeMessage::setModeAnnounceMessage(*message, recursive);
|
||||||
|
return EXECUTION_COMPLETE;
|
||||||
|
case (Subservice::COMMAND_MODE_READ):
|
||||||
|
ModeMessage::setModeReadMessage(*message);
|
||||||
|
return returnvalue::OK;
|
||||||
|
default:
|
||||||
|
return CommandingServiceBase::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
|
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
|
||||||
@ -73,8 +90,10 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
|
|||||||
ReturnValue_t result = returnvalue::FAILED;
|
ReturnValue_t result = returnvalue::FAILED;
|
||||||
switch (replyId) {
|
switch (replyId) {
|
||||||
case (ModeMessage::REPLY_MODE_REPLY): {
|
case (ModeMessage::REPLY_MODE_REPLY): {
|
||||||
result = prepareModeReply(reply, objectId);
|
if (previousCommand != ModeMessage::CMD_MODE_COMMAND) {
|
||||||
break;
|
return prepareModeReply(reply, objectId);
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
|
case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
|
||||||
result = prepareWrongModeReply(reply, objectId);
|
result = prepareWrongModeReply(reply, objectId);
|
||||||
|
@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase {
|
|||||||
COMMAND_MODE_READ = 3,
|
COMMAND_MODE_READ = 3,
|
||||||
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
|
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
|
||||||
//! This command does NOT have a reply
|
//! This command does NOT have a reply
|
||||||
COMMAND_MODE_ANNCOUNCE = 4,
|
COMMAND_MODE_ANNOUNCE = 4,
|
||||||
//!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
|
//!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
|
||||||
//! command to every child. This command does NOT have a reply.
|
//! command to every child. This command does NOT have a reply.
|
||||||
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,
|
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
#include "fsfw/pus/CService201HealthCommanding.h"
|
|
||||||
|
|
||||||
#include "fsfw/health/HasHealthIF.h"
|
|
||||||
#include "fsfw/health/HealthMessage.h"
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/pus/servicepackets/Service201Packets.h"
|
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
||||||
|
|
||||||
CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, uint16_t apid,
|
|
||||||
uint8_t serviceId,
|
|
||||||
uint8_t numParallelCommands,
|
|
||||||
uint16_t commandTimeoutSeconds)
|
|
||||||
: CommandingServiceBase(objectId, apid, "PUS 201 Health MGMT", serviceId, numParallelCommands,
|
|
||||||
commandTimeoutSeconds) {}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
|
||||||
switch (subservice) {
|
|
||||||
case (Subservice::COMMAND_SET_HEALTH):
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
|
|
||||||
return returnvalue::OK;
|
|
||||||
default:
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Invalid Subservice" << std::endl;
|
|
||||||
#endif
|
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subservice,
|
|
||||||
const uint8_t *tcData,
|
|
||||||
size_t tcDataLen,
|
|
||||||
MessageQueueId_t *id,
|
|
||||||
object_id_t *objectId) {
|
|
||||||
if (tcDataLen < sizeof(object_id_t)) {
|
|
||||||
return CommandingServiceBase::INVALID_TC;
|
|
||||||
}
|
|
||||||
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
|
||||||
|
|
||||||
return checkInterfaceAndAcquireMessageQueue(id, objectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
|
||||||
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
|
||||||
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
|
||||||
if (destination == nullptr) {
|
|
||||||
return CommandingServiceBase::INVALID_OBJECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*messageQueueToSet = destination->getCommandQueue();
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *message,
|
|
||||||
uint8_t subservice, const uint8_t *tcData,
|
|
||||||
size_t tcDataLen, uint32_t *state,
|
|
||||||
object_id_t objectId) {
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
switch (subservice) {
|
|
||||||
case (Subservice::COMMAND_SET_HEALTH): {
|
|
||||||
HealthSetCommand healthCommand;
|
|
||||||
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
|
|
||||||
healthCommand.getHealth());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// Should never happen, subservice was already checked
|
|
||||||
result = returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *reply,
|
|
||||||
Command_t previousCommand, uint32_t *state,
|
|
||||||
CommandMessage *optionalNextCommand,
|
|
||||||
object_id_t objectId, bool *isStep) {
|
|
||||||
Command_t replyId = reply->getCommand();
|
|
||||||
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
|
|
||||||
return EXECUTION_COMPLETE;
|
|
||||||
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
|
|
||||||
return reply->getReplyRejectedReason();
|
|
||||||
}
|
|
||||||
return CommandingServiceBase::INVALID_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not used for now, health state already reported by event
|
|
||||||
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
|
|
||||||
const CommandMessage *reply) {
|
|
||||||
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
|
||||||
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
|
||||||
HealthSetReply healthSetReply(health, oldHealth);
|
|
||||||
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
|
|
||||||
}
|
|
161
src/fsfw/pus/CServiceHealthCommanding.cpp
Normal file
161
src/fsfw/pus/CServiceHealthCommanding.cpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#include <fsfw/events/EventManagerIF.h>
|
||||||
|
#include <fsfw/pus/CServiceHealthCommanding.h>
|
||||||
|
|
||||||
|
#include "fsfw/health/HasHealthIF.h"
|
||||||
|
#include "fsfw/health/HealthMessage.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
#include "fsfw/pus/servicepackets/Service201Packets.h"
|
||||||
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args)
|
||||||
|
: CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service,
|
||||||
|
args.numParallelCommands, args.commandTimeoutSeconds),
|
||||||
|
healthTableId(args.table),
|
||||||
|
maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::initialize() {
|
||||||
|
ReturnValue_t result = CommandingServiceBase::initialize();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
healthTable = ObjectManager::instance()->get<HealthTable>(healthTableId);
|
||||||
|
if (healthTable == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) {
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
|
||||||
|
return returnvalue::OK;
|
||||||
|
default:
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Invalid Subservice" << std::endl;
|
||||||
|
#endif
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::getMessageQueueAndObject(uint8_t subservice,
|
||||||
|
const uint8_t *tcData,
|
||||||
|
size_t tcDataLen,
|
||||||
|
MessageQueueId_t *id,
|
||||||
|
object_id_t *objectId) {
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
||||||
|
if (tcDataLen < sizeof(object_id_t)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
|
||||||
|
return checkInterfaceAndAcquireMessageQueue(id, objectId);
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
||||||
|
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
||||||
|
if (destination == nullptr) {
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*messageQueueToSet = destination->getCommandQueue();
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen,
|
||||||
|
uint32_t *state, object_id_t objectId) {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH): {
|
||||||
|
if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
HealthSetCommand healthCommand;
|
||||||
|
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
|
||||||
|
healthCommand.getHealth());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
||||||
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
|
||||||
|
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
||||||
|
ReturnValue_t result = iterateHealthTable(true);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
reportAllHealth = true;
|
||||||
|
return EXECUTION_COMPLETE;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// Should never happen, subservice was already checked
|
||||||
|
result = returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::handleReply(const CommandMessage *reply,
|
||||||
|
Command_t previousCommand, uint32_t *state,
|
||||||
|
CommandMessage *optionalNextCommand,
|
||||||
|
object_id_t objectId, bool *isStep) {
|
||||||
|
Command_t replyId = reply->getCommand();
|
||||||
|
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
|
||||||
|
return EXECUTION_COMPLETE;
|
||||||
|
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
|
||||||
|
return reply->getReplyRejectedReason();
|
||||||
|
}
|
||||||
|
return CommandingServiceBase::INVALID_REPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CServiceHealthCommanding::doPeriodicOperation() {
|
||||||
|
if (reportAllHealth) {
|
||||||
|
for (uint8_t i = 0; i < maxNumHealthInfoPerCycle; i++) {
|
||||||
|
ReturnValue_t result = iterateHealthTable(false);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
reportAllHealth = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not used for now, health state already reported by event
|
||||||
|
[[maybe_unused]] ReturnValue_t CServiceHealthCommanding::prepareHealthSetReply(
|
||||||
|
const CommandMessage *reply) {
|
||||||
|
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
||||||
|
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
||||||
|
HealthSetReply healthSetReply(health, oldHealth);
|
||||||
|
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
|
||||||
|
std::pair<object_id_t, HasHealthIF::HealthState> pair;
|
||||||
|
|
||||||
|
ReturnValue_t result = healthTable->iterate(&pair, reset);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
EventManagerIF::triggerEvent(pair.first, HasHealthIF::HEALTH_INFO, pair.second, pair.second);
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,26 @@
|
|||||||
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
|
|
||||||
|
#include <fsfw/health/HealthTable.h>
|
||||||
|
|
||||||
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
||||||
|
|
||||||
|
struct HealthServiceCfg {
|
||||||
|
HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable,
|
||||||
|
uint16_t maxNumHealthInfoPerCycle)
|
||||||
|
: objectId(objectId),
|
||||||
|
apid(apid),
|
||||||
|
table(healthTable),
|
||||||
|
maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
|
||||||
|
object_id_t objectId;
|
||||||
|
uint16_t apid;
|
||||||
|
object_id_t table;
|
||||||
|
uint16_t maxNumHealthInfoPerCycle;
|
||||||
|
uint8_t service = 201;
|
||||||
|
uint8_t numParallelCommands = 4;
|
||||||
|
uint16_t commandTimeoutSeconds = 60;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom PUS service to set health of all objects
|
* @brief Custom PUS service to set health of all objects
|
||||||
* implementing hasHealthIF.
|
* implementing hasHealthIF.
|
||||||
@ -17,11 +35,12 @@
|
|||||||
* child class like this service
|
* child class like this service
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class CService201HealthCommanding : public CommandingServiceBase {
|
class CServiceHealthCommanding : public CommandingServiceBase {
|
||||||
public:
|
public:
|
||||||
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
CServiceHealthCommanding(HealthServiceCfg args);
|
||||||
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
~CServiceHealthCommanding() override = default;
|
||||||
~CService201HealthCommanding() override = default;
|
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* CSB abstract function implementations */
|
/* CSB abstract function implementations */
|
||||||
@ -37,7 +56,14 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
CommandMessage *optionalNextCommand, object_id_t objectId,
|
CommandMessage *optionalNextCommand, object_id_t objectId,
|
||||||
bool *isStep) override;
|
bool *isStep) override;
|
||||||
|
|
||||||
|
void doPeriodicOperation() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const object_id_t healthTableId;
|
||||||
|
HealthTable *healthTable;
|
||||||
|
uint16_t maxNumHealthInfoPerCycle = 0;
|
||||||
|
bool reportAllHealth = false;
|
||||||
|
ReturnValue_t iterateHealthTable(bool reset);
|
||||||
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
||||||
const object_id_t *objectId);
|
const object_id_t *objectId);
|
||||||
|
|
@ -7,9 +7,8 @@
|
|||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/serialize/SerializeAdapter.h"
|
#include "fsfw/serialize/SerializeAdapter.h"
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
|
||||||
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
|
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
|
||||||
#include "fsfw/globalfunctions/CRC.h"
|
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||||
|
|
||||||
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
||||||
|
|
||||||
|
@ -16,7 +16,9 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
|
|||||||
tcDestination(tcDestination)
|
tcDestination(tcDestination)
|
||||||
|
|
||||||
{
|
{
|
||||||
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
|
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
||||||
|
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
|
TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
|
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
|
||||||
@ -35,7 +37,7 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored) {
|
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
|
||||||
if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
|
if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
|
||||||
this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
|
this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
@ -143,13 +145,17 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
|||||||
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
|
||||||
|
|
||||||
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
|
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
|
||||||
storeDownlinkData(&message);
|
ReturnValue_t result = storeDownlinkData(&message);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
tmStore->deleteData(message.getStorageId());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = tmStore->getData(message.getStorageId(), &data, &size);
|
result = tmStore->getData(message.getStorageId(), &data, &size);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
status = result;
|
status = result;
|
||||||
|
tmStore->deleteData(message.getStorageId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,9 +163,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
status = result;
|
status = result;
|
||||||
} else {
|
} else {
|
||||||
tmStore->deleteData(message.getStorageId());
|
|
||||||
packetSentCounter++;
|
packetSentCounter++;
|
||||||
}
|
}
|
||||||
|
tmStore->deleteData(message.getStorageId());
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -171,6 +177,7 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tmFifo->full()) {
|
if (tmFifo->full()) {
|
||||||
|
if (warningSwitch) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
|
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||||
"of stored packet IDs reached!"
|
"of stored packet IDs reached!"
|
||||||
@ -180,6 +187,8 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
|
|||||||
"TmTcBridge::storeDownlinkData: TM downlink max. number "
|
"TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||||
"of stored packet IDs reached!\n");
|
"of stored packet IDs reached!\n");
|
||||||
#endif
|
#endif
|
||||||
|
warningSwitch = false;
|
||||||
|
}
|
||||||
if (overwriteOld) {
|
if (overwriteOld) {
|
||||||
tmFifo->retrieve(&storeId);
|
tmFifo->retrieve(&storeId);
|
||||||
tmStore->deleteData(storeId);
|
tmStore->deleteData(storeId);
|
||||||
@ -221,6 +230,7 @@ ReturnValue_t TmTcBridge::handleStoredTm() {
|
|||||||
packetSentCounter++;
|
packetSentCounter++;
|
||||||
|
|
||||||
if (tmFifo->empty()) {
|
if (tmFifo->empty()) {
|
||||||
|
warningSwitch = true;
|
||||||
tmStored = false;
|
tmStored = false;
|
||||||
}
|
}
|
||||||
tmStore->deleteData(storeId);
|
tmStore->deleteData(storeId);
|
||||||
|
@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
public:
|
public:
|
||||||
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
|
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
|
||||||
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
|
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
|
||||||
static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 200;
|
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
|
||||||
|
|
||||||
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
||||||
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
||||||
@ -42,7 +42,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
* @return -@c returnvalue::OK if value was set successfully
|
* @return -@c returnvalue::OK if value was set successfully
|
||||||
* -@c returnvalue::FAILED otherwise, stored value stays the same
|
* -@c returnvalue::FAILED otherwise, stored value stays the same
|
||||||
*/
|
*/
|
||||||
ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored);
|
ReturnValue_t setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will set up the bridge to overwrite old data in the FIFO.
|
* This will set up the bridge to overwrite old data in the FIFO.
|
||||||
@ -91,6 +91,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
//! by default, so telemetry will be handled immediately.
|
//! by default, so telemetry will be handled immediately.
|
||||||
bool communicationLinkUp = true;
|
bool communicationLinkUp = true;
|
||||||
bool tmStored = false;
|
bool tmStored = false;
|
||||||
|
bool warningSwitch = true;
|
||||||
bool overwriteOld = true;
|
bool overwriteOld = true;
|
||||||
uint8_t packetSentCounter = 0;
|
uint8_t packetSentCounter = 0;
|
||||||
|
|
||||||
@ -152,7 +153,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
*/
|
*/
|
||||||
DynamicFIFO<store_address_t>* tmFifo = nullptr;
|
DynamicFIFO<store_address_t>* tmFifo = nullptr;
|
||||||
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
||||||
uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
|
unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */
|
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "fsfw/FSFWVersion.h"
|
#include "fsfw/FSFWVersion.h"
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ fsfw::Version::Version(int major, int minor, int revision, const char* addInfo)
|
|||||||
|
|
||||||
void fsfw::Version::getVersion(char* str, size_t maxLen) const {
|
void fsfw::Version::getVersion(char* str, size_t maxLen) const {
|
||||||
size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
|
size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
|
||||||
if (addInfo != nullptr) {
|
if (addInfo != nullptr and std::strcmp(addInfo, "") != 0) {
|
||||||
snprintf(str + len, maxLen - len, "-%s", addInfo);
|
snprintf(str + len, maxLen - len, "-%s", addInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,7 +31,7 @@ namespace fsfw {
|
|||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
std::ostream& operator<<(std::ostream& os, const Version& v) {
|
std::ostream& operator<<(std::ostream& os, const Version& v) {
|
||||||
os << v.major << "." << v.minor << "." << v.revision;
|
os << v.major << "." << v.minor << "." << v.revision;
|
||||||
if (v.addInfo != nullptr) {
|
if (v.addInfo != nullptr and std::strcmp(v.addInfo, "") != 0) {
|
||||||
os << "-" << v.addInfo;
|
os << "-" << v.addInfo;
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user