diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index efd791e85b4902d773897aeb8ae48aa37dfc243b..5b44ac96da73d9acc2af3bb992aa3611e574d766 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,6 +1,7 @@ <component name="ProjectCodeStyleConfiguration"> <code_scheme name="Project" version="173"> <option name="RIGHT_MARGIN" value="100" /> + <option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" /> <Objective-C-extensions> <file> <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" /> diff --git a/CMakeLists.txt b/CMakeLists.txt index 810fb26f2782e19125dada4b8d651c4025ad71fa..40f819b605d47ef1805b71809de9e16eb927f141 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,10 +14,15 @@ add_custom_target(check WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/ci") # Specify the .cpp files for the executables -add_executable(ecss_services src/main.cpp src/Message.cpp src/Service.cpp src/Services/TestService.cpp src/Services/MemoryManagementService.cpp) +add_executable(ecss_services src/main.cpp src/Message.cpp src/Service.cpp + src/Services/TestService.cpp src/Services/MemoryManagementService.cpp + src/Services/RequestVerificationService.cpp) IF(EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt") -add_subdirectory(lib/Catch2) -add_executable(tests src/Message.cpp src/Services/TestService.cpp src/Services/MemoryManagementService.cpp test/tests.cpp test/Message.cpp test/TestPlatform.cpp test/Services/TestService.cpp test/Services/MemoryManagementService.cpp) -target_link_libraries(tests Catch2::Catch2) + add_subdirectory(lib/Catch2) + add_executable(tests src/Message.cpp src/Services/TestService.cpp + src/Services/RequestVerificationService.cpp src/Services/MemoryManagementService.cpp + test/tests.cpp test/Message.cpp test/TestPlatform.cpp test/Services/TestService.cpp + test/Services/MemoryManagementService.cpp test/Services/RequestVerificationService.cpp) + target_link_libraries(tests Catch2::Catch2) ENDIF() diff --git a/ci/cppcheck.sh b/ci/cppcheck.sh index 6da4d33694f44e13b0d05a789f359ce84a2e70f5..3b8d4cf3f1ee124eaa6787290a505837e7fefbaf 100755 --- a/ci/cppcheck.sh +++ b/ci/cppcheck.sh @@ -10,4 +10,4 @@ echo -e "\033[0;34mRunning cppcheck...\033[0m" cd "$(dirname "$0")/.." -cppcheck --enable=all --error-exitcode=1 -I inc src tests +cppcheck --enable=all --suppress=unusedFunction --suppress=missingIncludeSystem --error-exitcode=1 -I inc src tests diff --git a/inc/Services/RequestVerificationService.hpp b/inc/Services/RequestVerificationService.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f1d2bf9210a97e69bd6f2f6e2938bb1bd4ddb7e9 --- /dev/null +++ b/inc/Services/RequestVerificationService.hpp @@ -0,0 +1,98 @@ +#ifndef ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP +#define ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP + +#include "Service.hpp" + +/** + * Implementation of the ST[01] request verification service + * + * @todo All telemetry packets shall have a telemetry packet secondary header + * @todo See if it would be more efficient to use Messages as arguments instead of individual + * parameters + */ +class RequestVerificationService : public Service { +public: + RequestVerificationService() { + serviceType = 1; + } + + /** + * TM[1,1] successful acceptance verification report + * Send report when the Cubesat accepts successfully commands + * + * Note:The parameters are the necessary information, defined from the standard, that the report + * should contain + * + * @param apid Application process ID + * @param seqFlag Sequence flags + * @param packetSeqCount Packet sequence count + */ + void successAcceptanceVerification(Message::PacketType packetType, bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount); + + /** + * TM[1,2] failed acceptance verification report + *Send report when the Cubesat don't accept commands + * + * Note:The parameters are the necessary information, defined from the standard, that the report + * should contain + * + * @param apid Application process ID + * @param seqFlag Sequence flags + * @param packetSeqCount Packet sequence count + */ + void failAcceptanceVerification(Message::PacketType packetType, bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount, + uint16_t errorCode); + + + /** + * TM[1,7] successful completion of execution verification report + * Send report when the Cubesat completes an execution + * + * Note:The parameters are the necessary information, defined from the standard, that the report + * should contain + * + * @param apid Application process ID + * @param seqFlag Sequence flags + * @param packetSeqCount Packet sequence count + */ + void successExecutionVerification(Message::PacketType packetType, bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount); + + /** + * TM[1,8] failed completion of execution verification report + * Send report when the Cubesat don't complete an execution + * + * Note:The parameters are the necessary information, defined from the standard, that the report + * should contain + * + * @param apid Application process ID + * @param seqFlag Sequence flags + * @param packetSeqCount Packet sequence count + */ + void failExecutionVerification(Message::PacketType packetType, + bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount, + uint16_t errorCode); + + /** + * TM[1,10] failed routing verification report + * Send report when the routing of a request has failed + * + * Note:The parameters are the necessary information, defined from the standard, that the report + * should contain + * + * @param apid Application process ID + * @param seqFlag Sequence flags + * @param packetSeqCount Packet sequence count + */ + void failRoutingVerification(Message::PacketType packetType, + bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount, + uint16_t errorCode); + + +}; + +#endif //ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP diff --git a/inc/Services/TestService.hpp b/inc/Services/TestService.hpp index 1d367e9563701083e0c10efd9c1c82b3a9c34ae8..a3704aa16a0ca3b7d7a19c9d639983614f5d91fd 100644 --- a/inc/Services/TestService.hpp +++ b/inc/Services/TestService.hpp @@ -15,14 +15,14 @@ public: /** * TC[17,1] perform an are-you-alive connection test */ - void areYouAlive(Message & request); + void areYouAlive(Message &request); /** * TC[17,3] perform an on-board connection test * * @todo Only respond if we have the correct APID */ - void onBoardConnection(Message & request); + void onBoardConnection(Message &request); }; diff --git a/src/Message.cpp b/src/Message.cpp index 0e95ad323ef0e8b8ea4b53cf1b09c35ee734c398..60259a597339b14b686352bd67f4eb1ff8f1eb0d 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -1,6 +1,5 @@ #include "Message.hpp" #include <cstring> -#include <Message.hpp> Message::Message(uint8_t serviceType, uint8_t messageType, Message::PacketType packetType, diff --git a/src/Service.cpp b/src/Service.cpp index 27a9f4746007488ac3a881c5afda77d88adb581d..07403e438e1ff884b430c5eafff7d92a7d63c63c 100644 --- a/src/Service.cpp +++ b/src/Service.cpp @@ -7,9 +7,10 @@ void Service::storeMessage(const Message &message) { std::cout << "New " << ((message.packetType == Message::TM) ? "TM" : "TC") << "[" << std::dec << static_cast<int>(message.serviceType) << "," << static_cast<int>(message.messageType) << "] message!\n"; - std::cout << std::hex << std::setfill('0') << std::setw(2); + //std::cout << std::hex << std::setfill('0') << std::setw(2); for (int i = 0; i < message.dataSize; i++) { std::cout << static_cast<int>(message.data[i]); + std::cout << " "; } std::cout << std::endl; } diff --git a/src/Services/RequestVerificationService.cpp b/src/Services/RequestVerificationService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccacfb591ee31076c14501d29792e5b560c8130a --- /dev/null +++ b/src/Services/RequestVerificationService.cpp @@ -0,0 +1,126 @@ +#include "Services/RequestVerificationService.hpp" +#include "Message.hpp" + +void RequestVerificationService::successAcceptanceVerification(Message::PacketType packetType, + bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, + uint16_t packetSeqCount) { + // TM[1,1] successful acceptance verification report + + // parameters have max values defined from standard + assert(apid < 2048); + assert(seqFlag < 4); + assert(packetSeqCount < 16384); + + Message report = createTM(1); + + report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number + report.appendEnumerated(1, packetType); + report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag)); + report.appendEnumerated(11, apid); + report.appendEnumerated(2, seqFlag); + report.appendBits(14, packetSeqCount); + + storeMessage(report); +} + +void +RequestVerificationService::failAcceptanceVerification(Message::PacketType packetType, + bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, + uint16_t packetSeqCount, + uint16_t errorCode) { + // TM[1,2] failed acceptance verification report + + // parameters have max values defined from standard + assert(apid < 2048); + assert(seqFlag < 4); + assert(packetSeqCount < 16384); + + Message report = createTM(2); + + report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number + report.appendEnumerated(1, packetType); + report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag)); + report.appendEnumerated(11, apid); + report.appendEnumerated(2, seqFlag); + report.appendBits(14, packetSeqCount); + report.appendEnum16(errorCode); + + storeMessage(report); +} + +void RequestVerificationService::successExecutionVerification(Message::PacketType packetType, + bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, + uint16_t packetSeqCount) { + // TM[1,7] successful completion of execution verification report + + // parameters have max values defined from standard + assert(apid < 2048); + assert(seqFlag < 4); + assert(packetSeqCount < 16384); + + Message report = createTM(7); + + report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number + report.appendEnumerated(1, packetType); + report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag)); + report.appendEnumerated(11, apid); + report.appendEnumerated(2, seqFlag); + report.appendBits(14, packetSeqCount); + + storeMessage(report); +} + +void +RequestVerificationService::failExecutionVerification(Message::PacketType packetType, + bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, + uint16_t packetSeqCount, + uint16_t errorCode) { + // TM[1,8] failed completion of execution verification report + + // parameters have max values defined from standard + assert(apid < 2048); + assert(seqFlag < 4); + assert(packetSeqCount < 16384); + + Message report = createTM(8); + + report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number + report.appendEnumerated(1, packetType); + report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag)); + report.appendEnumerated(11, apid); + report.appendEnumerated(2, seqFlag); + report.appendBits(14, packetSeqCount); + report.appendEnum16(errorCode); + + storeMessage(report); +} + +void +RequestVerificationService::failRoutingVerification(Message::PacketType packetType, + bool secondaryHeaderFlag, + uint16_t apid, uint8_t seqFlag, + uint16_t packetSeqCount, + uint16_t errorCode) { + // TM[1,10] failed routing verification report + + // parameters have max values defined from standard + assert(apid < 2048); + assert(seqFlag < 4); + assert(packetSeqCount < 16384); + + Message report = createTM(10); + + report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number + report.appendEnumerated(1, packetType); + report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag)); + report.appendEnumerated(11, apid); + report.appendEnumerated(2, seqFlag); + report.appendBits(14, packetSeqCount); + report.appendEnum16(errorCode); + + storeMessage(report); +} diff --git a/src/Services/TestService.cpp b/src/Services/TestService.cpp index 06f60263866d9ed9192dc95385e7570b174a1bea..670a8e2fe18cdf1403490b7393d7e7e9030b01d9 100644 --- a/src/Services/TestService.cpp +++ b/src/Services/TestService.cpp @@ -12,6 +12,6 @@ void TestService::onBoardConnection(Message &request) { Message report = createTM(4); report.appendUint16(request.readUint16()); - + // just print it on the screen storeMessage(report); } diff --git a/src/main.cpp b/src/main.cpp index f9bf03e44f053f43426d2412914b80ad7aabde49..a65e88ca40567509f00b257cadd5445286980ef2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include <iostream> #include <Services/TestService.hpp> +#include <Services/RequestVerificationService.hpp> #include "Message.hpp" #include "Services/MemoryManagementService.hpp" @@ -17,7 +18,8 @@ int main() { char string[6]; packet.readString(string, 5); - std::cout << "Word: " << string << " " << packet.readBits(15) << packet.readBits(1) << std::endl; + std::cout << "Word: " << string << " " << packet.readBits(15) << packet.readBits(1) + << std::endl; std::cout << packet.readFloat() << " " << std::dec << packet.readSint32() << std::endl; // ST[17] test @@ -61,5 +63,14 @@ int main() { rcvPack.appendOctetString(1, data); memMangService.rawDataMemorySubservice.loadRawData(rcvPack); + // ST[01] test + // parameters take random values and works as expected + RequestVerificationService reqVerifService; + reqVerifService.successAcceptanceVerification(Message::TC, true, 2, 2, 10); + reqVerifService.failAcceptanceVerification(Message::TC, true, 2, 2, 10, 5); + reqVerifService.successExecutionVerification(Message::TC, true, 2, 2, 10); + reqVerifService.failExecutionVerification(Message::TC, true, 2, 2, 10, 6); + reqVerifService.failRoutingVerification(Message::TC, true, 2, 2, 10, 7); + return 0; } diff --git a/test/Services/RequestVerificationService.cpp b/test/Services/RequestVerificationService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c9e3c8ccda90deb72c48e62f585f6dd9394a7ba --- /dev/null +++ b/test/Services/RequestVerificationService.cpp @@ -0,0 +1,113 @@ +#include <catch2/catch.hpp> +#include <Services/RequestVerificationService.hpp> +#include <Message.hpp> +#include "ServiceTests.hpp" + +TEST_CASE("TM[1,1]", "[service][st01]") { + RequestVerificationService reqVerifService; + reqVerifService.successAcceptanceVerification(Message::TC, true, 2, 2, 10); + REQUIRE(ServiceTests::hasOneMessage()); + + Message response = ServiceTests::get(0); + // Checks for the data-members of the object response + CHECK(response.serviceType == 1); + CHECK(response.messageType == 1); + CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1) + CHECK(response.applicationId == 0); + REQUIRE(response.dataSize == 4); // dataSize is the number of bytes of data array + // Check for the value that is stored in <<data>> array(data-member of object response) + CHECK(response.readEnumerated(3) == 2); // packet version number + CHECK(response.readEnumerated(1) == 1); // packet type + CHECK(response.readBits(1) == true); // secondary header flag + CHECK(response.readEnumerated(11) == 2); // application process ID + CHECK(response.readEnumerated(2) == 2); // sequence flags + CHECK(response.readBits(14) == 10); // packet sequence count +} + +TEST_CASE("TM[1,2]", "[service][st01]") { + RequestVerificationService reqVerifService; + reqVerifService.failAcceptanceVerification(Message::TC, true, 2, 2, 10, 5); + REQUIRE(ServiceTests::hasOneMessage()); + + Message response = ServiceTests::get(0); + // Checks for the data-members of the object response + CHECK(response.serviceType == 1); + CHECK(response.messageType == 2); + CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1) + CHECK(response.applicationId == 0); + REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array + // Check for the value that is stored in <<data>> array(data-member of object response) + CHECK(response.readEnumerated(3) == 2); // packet version number + CHECK(response.readEnumerated(1) == 1); // packet type + CHECK(response.readBits(1) == true); // secondary header flag + CHECK(response.readEnumerated(11) == 2); // application process ID + CHECK(response.readEnumerated(2) == 2); // sequence flags + CHECK(response.readBits(14) == 10); // packet sequence count + CHECK(response.readEnum16() == 5); // error code +} + +TEST_CASE("TM[1,7]", "[service][st01]") { + RequestVerificationService reqVerifService; + reqVerifService.successExecutionVerification(Message::TC, true, 2, 2, 10); + REQUIRE(ServiceTests::hasOneMessage()); + + Message response = ServiceTests::get(0); + // Checks for the data-members of the object response + CHECK(response.serviceType == 1); + CHECK(response.messageType == 7); + CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1) + CHECK(response.applicationId == 0); + REQUIRE(response.dataSize == 4); // dataSize is the number of bytes of data array + // Check for the value that is stored in <<data>> array(data-member of object response) + CHECK(response.readEnumerated(3) == 2); // packet version number + CHECK(response.readEnumerated(1) == 1); // packet type + CHECK(response.readBits(1) == true); // secondary header flag + CHECK(response.readEnumerated(11) == 2); // application process ID + CHECK(response.readEnumerated(2) == 2); // sequence flags + CHECK(response.readBits(14) == 10); // packet sequence count +} + +TEST_CASE("TM[1,8]", "[service][st01]") { + RequestVerificationService reqVerifService; + reqVerifService.failExecutionVerification(Message::TC, true, 2, 2, 10, 6); + REQUIRE(ServiceTests::hasOneMessage()); + + Message response = ServiceTests::get(0); + // Checks for the data-members of the object response + CHECK(response.serviceType == 1); + CHECK(response.messageType == 8); + CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1) + CHECK(response.applicationId == 0); + REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array + // Check for the value that is stored in <<data>> array(data-member of object response) + CHECK(response.readEnumerated(3) == 2); // packet version number + CHECK(response.readEnumerated(1) == 1); // packet type + CHECK(response.readBits(1) == true); // secondary header flag + CHECK(response.readEnumerated(11) == 2); // application process ID + CHECK(response.readEnumerated(2) == 2); // sequence flags + CHECK(response.readBits(14) == 10); // packet sequence count + CHECK(response.readEnum16() == 6); // error code +} + +TEST_CASE("TM[1,10]", "[service][st01]") { + RequestVerificationService reqVerifService; + reqVerifService.failRoutingVerification(Message::TC, true, 2, 2, 10, 7); + REQUIRE(ServiceTests::hasOneMessage()); + + Message response = ServiceTests::get(0); + // Checks for the data-members of the object response + CHECK(response.serviceType == 1); + CHECK(response.messageType == 10); + CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1) + CHECK(response.applicationId == 0); + REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array + // Check for the value that is stored in <<data>> array(data-member of object response) + CHECK(response.readEnumerated(3) == 2); // packet version number + CHECK(response.readEnumerated(1) == 1); // packet type + CHECK(response.readBits(1) == true); // secondary header flag + CHECK(response.readEnumerated(11) == 2); // application process ID + CHECK(response.readEnumerated(2) == 2); // sequence flags + CHECK(response.readBits(14) == 10); // packet sequence count + CHECK(response.readEnum16() == 7); // error code +} +