diff --git a/CMakeLists.txt b/CMakeLists.txt index a6c978bb8f90be6c505788c684b0ad8563498f72..71a9f50c7e7ae4cccb7cae6072a0baa40e842cd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,9 +17,9 @@ add_custom_target(check add_library(common OBJECT src/ErrorHandler.cpp src/Message.cpp - src/MessageParser.cpp + src/MessageParser.cpp src/Helpers/CRCHelper.cpp - src/Services/EventReportService.cpp + src/Services/EventReportService.cpp src/Services/MemoryManagementService.cpp src/Services/ParameterService.cpp src/Services/RequestVerificationService.cpp @@ -41,5 +41,6 @@ IF (EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt") $<TARGET_OBJECTS:common> ${test_main_SRC} ${test_SRC}) + target_link_libraries(tests Catch2::Catch2) ENDIF () diff --git a/inc/Services/EventReportService.hpp b/inc/Services/EventReportService.hpp index 4f516648a2a681a17eb14879d2c676dd7fb56164..026262b182d5783c0f2cad9a0e0fa5328b6ed105 100644 --- a/inc/Services/EventReportService.hpp +++ b/inc/Services/EventReportService.hpp @@ -2,11 +2,12 @@ #define ECSS_SERVICES_EVENTREPORTSERVICE_HPP #include "Service.hpp" +#include <bitset> /** * Implementation of ST[05] event reporting service * @todo add enum event definition id (and maybe some appending?) * - * @todo changes enums event IDs + * @todo add more enums event IDs * * Note: enum IDs are these just for test purposes * @@ -15,15 +16,48 @@ #define ECSS_EVENTS_BITS 16 class EventReportService : public Service { +private: + static const uint16_t numberOfEvents = 7; + std::bitset<numberOfEvents> stateOfEvents; public: + // Variables that count the event reports per severity level + uint16_t lowSeverityReportCount; + uint16_t mediumSeverityReportCount; + uint16_t highSeverityReportCount; + + // Variables that count the event occurences per severity level + uint16_t lowSeverityEventCount; + uint16_t mediumSeverityEventCount; + uint16_t highSeverityEventCount; + + uint16_t disabledEventsCount; + + uint16_t lastLowSeverityReportID; + uint16_t lastMediumSeverityReportID; + uint16_t lastHighSeverityReportID; + EventReportService() { + stateOfEvents.set(); serviceType = 5; + lowSeverityReportCount = 0; + mediumSeverityReportCount = 0; + highSeverityReportCount = 0; + disabledEventsCount = 0; + lowSeverityEventCount = 0; + mediumSeverityEventCount = 0; + highSeverityEventCount = 0; + lastLowSeverityReportID = 65535; + lastMediumSeverityReportID = 65535; + lastHighSeverityReportID = 65535; } /** * Type of the information event + * + * Note: Numbers are kept in code explicitly, so that there is no uncertainty when something + * changes. */ - enum InformationEvent { + enum Event { /** * An unknown event occured */ @@ -33,96 +67,116 @@ public: */ WWDGReset = 1, /** - * An assertion has failed + * Assertion has failed */ AssertionFail = 2, /** * Microcontroller has started */ MCUStart = 3, - }; - - /** - * Type of the low severity anomaly event - */ - enum LowSeverityAnomalyEvent { /** * An unknown anomaly of low severity anomalyhas occurred */ - LowSeverityUnknownEvent = 1, - }; - - /** - * Type of the medium severity anomaly event - */ - enum MediumSeverityAnomalyEvent { + LowSeverityUnknownEvent = 4, /** * An unknown anomaly of medium severity has occurred */ - MediumSeverityUnknownEvent = 2, - }; - - /** - * Type of the high severity anomaly event - */ - enum HighSeverityAnomalyEvent { + MediumSeverityUnknownEvent = 5, /** * An unknown anomaly of high severity has occurred */ - HighSeverityUnknownEvent = 3, + HighSeverityUnknownEvent = 6, + /** + * When an execution of a notification/event fails to start + */ + FailedStartOfExecution = 7 }; /** * TM[5,1] informative event report * Send report to inform the respective recipients about an event * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ - void informativeEventReport(InformationEvent eventID, const uint8_t *data, uint8_t length); + void informativeEventReport(Event eventID, const uint8_t *data, uint8_t length); /** * TM[5,2] low severiity anomaly report * Send report when there is an anomaly event of low severity to the respective recipients * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ void - lowSeverityAnomalyReport(LowSeverityAnomalyEvent eventID, const uint8_t *data, uint8_t length); + lowSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length); /** * TM[5,3] medium severity anomaly report * Send report when there is an anomaly event of medium severity to the respective recipients * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ - void mediumSeverityAnomalyReport(MediumSeverityAnomalyEvent eventID, const uint8_t *data, + void mediumSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length); /** * TM[5,4] high severity anomaly report - * Send report when there is an anomaly event of hgih severity to the respective recipients + * Send report when there is an anomaly event of high severity to the respective recipients * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ - void highSeverityAnomalyReport(HighSeverityAnomalyEvent eventID, const uint8_t *data, + void highSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length); + /** + * TC[5,5] request to enable report generation + * Telecommand to enable the report generation of event definitions + */ + void enableReportGeneration(Message message); + + /** + * TC[5,6] request to disable report generation + * Telecommand to disable the report generation of event definitions + * @param message + */ + void disableReportGeneration(Message message); + + /** + * TC[5,7] request to report the disabled event definitions + * Note: No arguments, according to the standard. + * @param message + */ + void requestListOfDisabledEvents(Message message); + + /** + * TM[5,8] disabled event definitions report + * Telemetry package of a report of the disabled event definitions + * @param message + */ + void listOfDisabledEventsReport(); + + /** + * Getter for stateOfEvents bitset + * @return stateOfEvents, just in case the whole bitset is needed + */ + std::bitset<numberOfEvents> getStateOfEvents() { + return stateOfEvents; + } }; #endif //ECSS_SERVICES_EVENTREPORTSERVICE_HPP diff --git a/lib/Catch2 b/lib/Catch2 index 77f29c2f1cde8bd2e17f06cc04092b990d2acc2c..62460fafe6b54c3173bc5cbc46d05a5f071017ff 160000 --- a/lib/Catch2 +++ b/lib/Catch2 @@ -1 +1 @@ -Subproject commit 77f29c2f1cde8bd2e17f06cc04092b990d2acc2c +Subproject commit 62460fafe6b54c3173bc5cbc46d05a5f071017ff diff --git a/src/Services/EventReportService.cpp b/src/Services/EventReportService.cpp index 0a89f5c9765aa49e8932c0df9c1a4f1ed732a4ac..d49cef3c7ca31b184bfae618c6007e2245fb1865 100644 --- a/src/Services/EventReportService.cpp +++ b/src/Services/EventReportService.cpp @@ -1,46 +1,130 @@ +#include <Services/EventReportService.hpp> #include "Services/EventReportService.hpp" #include "Message.hpp" - -void EventReportService::informativeEventReport(InformationEvent eventID, const uint8_t *data, +/** + * @todo: Add message type in TCs + * @todo: this code is error prone, depending on parameters given, add fail safes (probably?) + */ +void EventReportService::informativeEventReport(Event eventID, const uint8_t *data, uint8_t length) { // TM[5,1] - Message report = createTM(1); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + Message report = createTM(1); + report.appendEnum16(eventID); + report.appendString(length, data); - storeMessage(report); + storeMessage(report); + } } void -EventReportService::lowSeverityAnomalyReport(LowSeverityAnomalyEvent eventID, const uint8_t *data, +EventReportService::lowSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length) { + lowSeverityEventCount++; // TM[5,2] - Message report = createTM(2); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + lowSeverityReportCount++; + Message report = createTM(2); + report.appendEnum16(eventID); + report.appendString(length, data); + lastLowSeverityReportID = static_cast<uint16_t >(eventID); - storeMessage(report); + storeMessage(report); + } } -void EventReportService::mediumSeverityAnomalyReport(MediumSeverityAnomalyEvent eventID, - const uint8_t *data, - uint8_t length) { +void EventReportService::mediumSeverityAnomalyReport(Event eventID, + const uint8_t *data, uint8_t length) { + mediumSeverityEventCount++; // TM[5,3] - Message report = createTM(3); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + mediumSeverityReportCount++; + Message report = createTM(3); + report.appendEnum16(eventID); + report.appendString(length, data); + lastMediumSeverityReportID = static_cast<uint16_t >(eventID); - storeMessage(report); + storeMessage(report); + } } void -EventReportService::highSeverityAnomalyReport(HighSeverityAnomalyEvent eventID, const uint8_t *data, +EventReportService::highSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length) { + highSeverityEventCount++; // TM[5,4] - Message report = createTM(4); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + highSeverityReportCount++; + Message report = createTM(4); + report.appendEnum16(eventID); + report.appendString(length, data); + lastHighSeverityReportID = static_cast<uint16_t >(eventID); + + storeMessage(report); + } +} + +void EventReportService::enableReportGeneration(Message message) { + // TC[5,5] + if (message.serviceType == 5 && message.packetType == Message::TC && message.messageType == 5) { + /** + * @todo: Report an error if length > numberOfEvents + */ + uint16_t length = message.readUint16(); + Event eventID[length]; + for (uint16_t i = 0; i < length; i++) { + eventID[i] = static_cast<Event >(message.readEnum16()); + } + if (length <= numberOfEvents) { + for (uint16_t i = 0; i < length; i++) { + stateOfEvents[static_cast<uint16_t> (eventID[i])] = 1; + } + } + disabledEventsCount = stateOfEvents.size() - stateOfEvents.count(); + } +} + +void EventReportService::disableReportGeneration(Message message) { + // TC[5,6] + if (message.serviceType == 5 && message.packetType == Message::TC && message.messageType + == 6) { + /** + * @todo: Report an error if length > numberOfEvents + */ + uint16_t length = message.readUint16(); + Event eventID[length]; + for (uint16_t i = 0; i < length; i++) { + eventID[i] = static_cast<Event >(message.readEnum16()); + } + if (length <= numberOfEvents) { + for (uint16_t i = 0; i < length; i++) { + stateOfEvents[static_cast<uint16_t> (eventID[i])] = 0; + } + } + disabledEventsCount = stateOfEvents.size() - stateOfEvents.count(); + } +} + +void EventReportService::requestListOfDisabledEvents(Message message) { + // TC[5,7] + // I think this is all that is needed here. + if (message.serviceType == 5 && message.packetType == Message::TC && message.messageType == 7) { + listOfDisabledEventsReport(); + } +} + +void EventReportService::listOfDisabledEventsReport() { + // TM[5,8] + Message report = createTM(8); + + uint16_t numberOfDisabledEvents = stateOfEvents.size() - stateOfEvents.count(); + report.appendHalfword(numberOfDisabledEvents); + for (uint16_t i = 0; i < stateOfEvents.size(); i++) { + if (stateOfEvents[i] == 0) { + report.appendEnum16(i); + } + } storeMessage(report); } diff --git a/src/main.cpp b/src/main.cpp index 0883b6023edfb55e97d1300e4372a3a68039fa0e..dfe9fa685bdb23a929d4bd8975f5f8468d40266f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -125,7 +125,7 @@ int main() { receivedMessage = Message(1, 10, Message::TC, 3); reqVerifService.failRoutingVerification(receivedMessage); - // ST[05] test [works] + // ST[05] (5,1 to 5,4) test [works] const unsigned char eventReportData[12] = "Hello World"; EventReportService eventReportService; eventReportService.informativeEventReport(EventReportService::InformativeUnknownEvent, @@ -169,5 +169,24 @@ int main() { errorMessage.appendBits(2, 7); errorMessage.appendByte(15); + // ST[05] (5,5 to 5,8) test [works] + EventReportService::Event eventIDs[] = {EventReportService::HighSeverityUnknownEvent, + EventReportService::MediumSeverityUnknownEvent}; + EventReportService::Event eventIDs2[] = {EventReportService::HighSeverityUnknownEvent}; + Message eventMessage(5, 6, Message::TC, 1); + eventMessage.appendUint16(2); + eventMessage.appendEnum16(eventIDs[0]); + eventMessage.appendEnum16(eventIDs[1]); + + Message eventMessage2(5, 5, Message::TC, 1); + eventMessage2.appendUint16(1); + eventMessage2.appendEnum16(eventIDs2[0]); + + Message eventMessage3(5, 7, Message::TC, 1); + eventReportService.disableReportGeneration(eventMessage); + eventReportService.listOfDisabledEventsReport(); + eventReportService.enableReportGeneration(eventMessage2); + eventReportService.requestListOfDisabledEvents(eventMessage3); + return 0; } diff --git a/test/Services/EventReportService.cpp b/test/Services/EventReportService.cpp index 32f4f30b18ee8d9e38c9c5a059fcfd07ad27c9f1..f326e76841d6ea0638db8d648db98ff94db73a08 100644 --- a/test/Services/EventReportService.cpp +++ b/test/Services/EventReportService.cpp @@ -42,7 +42,7 @@ TEST_CASE("Low Severity Anomaly Report TM[5,2]", "[service][st05]") { CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) REQUIRE(report.dataSize == 12); // Check for the value that is stored in <<data>> array(data-member of object response) - CHECK(report.readEnum16() == 1); + CHECK(report.readEnum16() == 4); report.readString(checkString, 10); CHECK(strcmp(checkString, reinterpret_cast<const char *>(eventReportData)) == 0); } @@ -62,7 +62,7 @@ TEST_CASE("Medium Severity Anomaly Report TM[5,3]", "[service][st05]") { CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) REQUIRE(report.dataSize == 12); // Check for the value that is stored in <<data>> array(data-member of object response) - CHECK(report.readEnum16() == 2); + CHECK(report.readEnum16() == 5); report.readString(checkString, 10); CHECK(strcmp(checkString, reinterpret_cast<const char *>(eventReportData)) == 0); } @@ -82,7 +82,106 @@ TEST_CASE("High Severity Anomaly Report TM[5,4]", "[service][st05]") { CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) REQUIRE(report.dataSize == 12); // Check for the value that is stored in <<data>> array(data-member of object response) - CHECK(report.readEnum16() == 3); + CHECK(report.readEnum16() == 6); report.readString(checkString, 10); CHECK(strcmp(checkString, reinterpret_cast<const char *>(eventReportData)) == 0); } + +TEST_CASE("Enable Report Generation TC[5,5]", "[service][st05]") { + EventReportService eventReportService; + eventReportService.getStateOfEvents().reset(); + EventReportService::Event eventID[] = {EventReportService::AssertionFail, + EventReportService::LowSeverityUnknownEvent}; + Message message(5, 5, Message::TC, 1); + message.appendUint16(2); + message.appendEnum16(eventID[0]); + message.appendEnum16(eventID[1]); + eventReportService.enableReportGeneration(message); + CHECK(eventReportService.getStateOfEvents()[2] == 1); + CHECK(eventReportService.getStateOfEvents()[4] == 1); +} + +TEST_CASE("Disable Report Generation TC[5,6]", "[service][st05]") { + EventReportService eventReportService; + EventReportService::Event eventID[] = {EventReportService::InformativeUnknownEvent, + EventReportService::MediumSeverityUnknownEvent}; + Message message(5, 6, Message::TC, 1); + message.appendUint16(2); + message.appendEnum16(eventID[0]); + message.appendEnum16(eventID[1]); + eventReportService.disableReportGeneration(message); + CHECK(eventReportService.getStateOfEvents()[0] == 0); + CHECK(eventReportService.getStateOfEvents()[5] == 0); + + const unsigned char eventReportData[] = "HelloWorld"; + eventReportService.highSeverityAnomalyReport(EventReportService::InformativeUnknownEvent, + eventReportData, 10); + CHECK(ServiceTests::hasOneMessage() == false); +} + +TEST_CASE("Request list of disabled events TC[5,7]", "[service][st05]") { + EventReportService eventReportService; + Message message(5, 7, Message::TC, 1); + eventReportService.requestListOfDisabledEvents(message); + REQUIRE(ServiceTests::hasOneMessage()); + + Message report = ServiceTests::get(0); + // Check if there is message of type 8 created + CHECK(report.messageType == 8); +} + +TEST_CASE("List of Disabled Events Report TM[5,8]", "[service][st05]") { + EventReportService eventReportService; + EventReportService::Event eventID[] = {EventReportService::MCUStart, + EventReportService::HighSeverityUnknownEvent}; + Message message(5, 6, Message::TC, 1); + message.appendUint16(2); + message.appendEnum16(eventID[0]); + message.appendEnum16(eventID[1]); + // Disable 3rd and 6th + eventReportService.disableReportGeneration(message); + eventReportService.listOfDisabledEventsReport(); + REQUIRE(ServiceTests::hasOneMessage()); + + Message report = ServiceTests::get(0); + // Check for the data-members of the report Message created + CHECK(report.serviceType == 5); + CHECK(report.messageType == 8); + CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) + REQUIRE(report.dataSize == 6); + // Check for the information stored in report + CHECK(report.readHalfword() == 2); + CHECK(report.readEnum16() == 3); + CHECK(report.readEnum16() == 6); +} + +TEST_CASE("List of observables 6.5.6", "[service][st05]") { + EventReportService eventReportService; + EventReportService::Event eventID[] = {EventReportService::HighSeverityUnknownEvent}; + Message message(5, 6, Message::TC, 1); + message.appendUint16(1); + message.appendEnum16(eventID[0]); + eventReportService.disableReportGeneration(message); + + const unsigned char eventReportData[] = "HelloWorld"; + + eventReportService.highSeverityAnomalyReport(EventReportService::HighSeverityUnknownEvent, + eventReportData, + 10); + eventReportService.mediumSeverityAnomalyReport(EventReportService::MediumSeverityUnknownEvent, + eventReportData, + 10); + CHECK(eventReportService.lowSeverityReportCount == 0); + CHECK(eventReportService.mediumSeverityReportCount == 1); + CHECK(eventReportService.highSeverityReportCount == 0); + + CHECK(eventReportService.lowSeverityEventCount == 0); + CHECK(eventReportService.mediumSeverityEventCount == 1); + CHECK(eventReportService.highSeverityEventCount == 1); + + CHECK(eventReportService.disabledEventsCount == 1); + + CHECK(eventReportService.lastLowSeverityReportID == 65535); + CHECK(eventReportService.lastMediumSeverityReportID == 5); + CHECK(eventReportService.lastHighSeverityReportID == 65535); +}