diff --git a/inc/Helpers/HousekeepingStructure.hpp b/inc/Helpers/HousekeepingStructure.hpp index 1e75430829b003bf49b83002a59dfddc068879f6..98271aa37526f9b4254d357b454e9b871ed96a64 100644 --- a/inc/Helpers/HousekeepingStructure.hpp +++ b/inc/Helpers/HousekeepingStructure.hpp @@ -14,20 +14,22 @@ */ class HousekeepingStructure { public: - uint8_t structureId; - /** - * Defined as integer multiples of the minimum sampling interval as per 6.3.3.2.c.5 #NOTE-2. - */ - uint32_t collectionInterval = 0; - /** - * Indicates whether the periodic generation of housekeeping reports is enabled. - */ - bool periodicGenerationActionStatus = false; + uint8_t structureId; - /** - * Vector containing the IDs of the simply commutated parameters, contained in the housekeeping structure. - */ - etl::vector<uint16_t, ECSSMaxSimplyCommutatedParameters> simplyCommutatedParameterIds; + /** + * Defined as integer multiples of the minimum sampling interval as per 6.3.3.2.c.5 #NOTE-2. + */ + uint32_t collectionInterval = 0; + + /** + * Indicates whether the periodic generation of housekeeping reports is enabled. + */ + bool periodicGenerationActionStatus = false; + + /** + * Vector containing the IDs of the simply commutated parameters, contained in the housekeeping structure. + */ + etl::vector<uint16_t, ECSSMaxSimplyCommutatedParameters> simplyCommutatedParameterIds; HousekeepingStructure() = default; }; diff --git a/inc/Services/HousekeepingService.hpp b/inc/Services/HousekeepingService.hpp index 2b6ac2331e711fd0b144b162ed548c5a51de8df0..2336f094e8e15a0afee5f28927502541494fee86 100644 --- a/inc/Services/HousekeepingService.hpp +++ b/inc/Services/HousekeepingService.hpp @@ -31,6 +31,12 @@ private: static bool existsInVector(const etl::vector<uint16_t, ECSSMaxSimplyCommutatedParameters>& ids, uint16_t parameterId); + /** + * Initializes Housekeeping Structures with the Parameters found in the obc-software. + * The function definition is also found in the obc-software repo. + */ + void initializeHousekeepingStructures(); + public: inline static const uint8_t ServiceType = 3; @@ -54,7 +60,9 @@ public: HousekeepingPeriodicPropertiesReport = 35, }; - HousekeepingService() = default; + HousekeepingService() { + initializeHousekeepingStructures(); + }; /** * Implementation of TC[3,1]. Request to create a housekeeping parameters report structure. @@ -121,6 +129,19 @@ public: */ void reportHousekeepingPeriodicProperties(Message& request); + /** + * This function calculates the time needed to pass until the next periodic report for each housekeeping + * structure. The function also calls the housekeeping reporting functions as needed. + * + * @note Three arguments are needed for resiliency in case the function doesn't execute at the exact time that is expected + * + * @param currentTime The current system time, in milliseconds. + * @param previousTime The system time of the previous call of the function. + * @param expectedDelay The output of this function after its last execution. + * @return uint32_t The minimum amount of time until the next periodic housekeeping report, in milliseconds. + */ + uint32_t reportPendingStructures(uint32_t currentTime, uint32_t previousTime, uint32_t expectedDelay); + /** * It is responsible to call the suitable function that executes a TC packet. The source of that packet * is the ground station. diff --git a/src/Platform/x86/HousekeepingService.cpp b/src/Platform/x86/HousekeepingService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..218f2223c8d6e0171fc437238d0a0088e8455121 --- /dev/null +++ b/src/Platform/x86/HousekeepingService.cpp @@ -0,0 +1,17 @@ +#include "ECSS_Configuration.hpp" + +#ifdef SERVICE_HOUSEKEEPING + +#include "Services/HousekeepingService.hpp" +#include "Parameters/PlatformParameters.hpp" + +void HousekeepingService::initializeHousekeepingStructures() { + HousekeepingStructure structure; + structure.structureId = 1; + structure.periodicGenerationActionStatus = true; + structure.collectionInterval = 500; + structure.simplyCommutatedParameterIds = {PlatformParameters::parameter1.getValue()}; + housekeepingStructures.insert({structure.structureId, structure}); +} + +#endif \ No newline at end of file diff --git a/src/Services/HousekeepingService.cpp b/src/Services/HousekeepingService.cpp index 1eefcbffc86c4c75956fc6b6a55377fa3e6a2be3..35beaa2ab3163197ebd778e805a408c739beeaea 100644 --- a/src/Services/HousekeepingService.cpp +++ b/src/Services/HousekeepingService.cpp @@ -259,3 +259,28 @@ bool HousekeepingService::existsInVector(const etl::vector<uint16_t, ECSSMaxSimp uint16_t parameterId) { return std::find(std::begin(ids), std::end(ids), parameterId) != std::end(ids); } + +uint32_t +HousekeepingService::reportPendingStructures(uint32_t currentTime, uint32_t previousTime, uint32_t expectedDelay) { + uint32_t nextCollection = std::numeric_limits<uint32_t>::max(); + + for (auto &housekeepingStructure: housekeepingStructures) { + if (housekeepingStructure.second.collectionInterval == 0) { + housekeepingParametersReport(housekeepingStructure.second.structureId); + nextCollection = 0; + continue; + } + if (currentTime != 0 and (currentTime % housekeepingStructure.second.collectionInterval == 0 or + (previousTime + expectedDelay) % housekeepingStructure.second.collectionInterval == + 0)) { + housekeepingParametersReport(housekeepingStructure.second.structureId); + } + uint32_t structureTimeToCollection = housekeepingStructure.second.collectionInterval - + currentTime % housekeepingStructure.second.collectionInterval; + if (nextCollection > structureTimeToCollection) { + nextCollection = structureTimeToCollection; + } + } + + return nextCollection; +} diff --git a/test/Services/HousekeepingService.cpp b/test/Services/HousekeepingService.cpp index c26ce5119b41c816591a90c389b4a8608d2e8134..459ec7528c0c502c1e7124a242ac2b0e9cedaa2b 100644 --- a/test/Services/HousekeepingService.cpp +++ b/test/Services/HousekeepingService.cpp @@ -23,6 +23,12 @@ void buildRequest(Message& request, uint8_t idToCreate) { } } +/** + * Stub function to define the HousekeepingService constructor during tests + */ +void HousekeepingService::initializeHousekeepingStructures() { +} + /** * Initializes 3 housekeeping structures with IDs = {0, 4, 6} */ @@ -618,3 +624,67 @@ TEST_CASE("Reporting of housekeeping structure periodic properties") { Services.reset(); } } + +TEST_CASE("Periodically reporting Housekeeping Structures") { + uint32_t nextCollection = 0; + uint32_t currentTime = 0; + uint32_t previousTime = 0; + SECTION("Non existent structures") { + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + CHECK(ServiceTests::count() == 0); + CHECK(nextCollection == std::numeric_limits<uint32_t>::max()); + } + SECTION("Collection Intervals set to max") { + initializeHousekeepingStructures(); + for (auto &housekeepingStructure: housekeepingService.housekeepingStructures) { + housekeepingStructure.second.collectionInterval = std::numeric_limits<uint32_t>::max(); + } + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + CHECK(ServiceTests::count() == 0); + CHECK(nextCollection == std::numeric_limits<uint32_t>::max()); + } + SECTION("Calculating properly defined collection intervals") { + housekeepingService.housekeepingStructures.at(0).collectionInterval = 900; + housekeepingService.housekeepingStructures.at(4).collectionInterval = 1000; + housekeepingService.housekeepingStructures.at(6).collectionInterval = 2700; + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + previousTime = currentTime; + currentTime += nextCollection; + CHECK(currentTime == 900); + CHECK(ServiceTests::count() == 0); + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + previousTime = currentTime; + currentTime += nextCollection; + CHECK(currentTime == 1000); + CHECK(ServiceTests::count() == 1); + currentTime += 6; + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + previousTime = currentTime; + currentTime += nextCollection; + CHECK(currentTime == 1800); + CHECK(ServiceTests::count() == 2); + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + previousTime = currentTime; + currentTime += nextCollection; + CHECK(ServiceTests::count() == 3); + CHECK(currentTime == 2000); + currentTime += 15; + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + previousTime = currentTime; + currentTime += nextCollection; + CHECK(ServiceTests::count() == 4); + CHECK(currentTime == 2700); + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + previousTime = currentTime; + currentTime += nextCollection; + CHECK(ServiceTests::count() == 6); + CHECK(currentTime == 3000); + } + SECTION("Collection Intervals set to 0") { + for (auto &housekeepingStructure: housekeepingService.housekeepingStructures) { + housekeepingStructure.second.collectionInterval = 0; + } + nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); + CHECK(nextCollection == 0); + } +} \ No newline at end of file