diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b046fbdf84bdb2de8dcf8f30a35096a515b4f73..37b151c03e16be403d2d367a27ca5daffbd2b092 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,8 +28,9 @@ add_library(common OBJECT src/Services/RequestVerificationService.cpp src/Services/TestService.cpp src/Services/TimeManagementService.cpp - src/Services/TimeBasedSchedulingService.cpp + src/Services/LargePacketTransferService.cpp src/Services/EventActionService.cpp + src/Services/TimeBasedSchedulingService.cpp src/Services/FunctionManagementService.cpp ) diff --git a/inc/ECSS_Definitions.hpp b/inc/ECSS_Definitions.hpp index de8033326c5e80391f4729fd889124f331bcc919..047db0f70cda0a66d4069ffb7aacd3c780e45baf 100644 --- a/inc/ECSS_Definitions.hpp +++ b/inc/ECSS_Definitions.hpp @@ -5,6 +5,8 @@ #define ECSS_MAX_STRING_SIZE 256 +#define ECSS_MAX_FIXED_OCTET_STRING_SIZE 256 // For the ST13 large packet transfer service + // 7.4.1 #define CCSDS_PACKET_VERSION 0 diff --git a/inc/ServicePool.hpp b/inc/ServicePool.hpp index d928606dea82a53552f14b999559f9b6b9bb61f6..d8ec83c84eef6be474397028868a89eef78f9d60 100644 --- a/inc/ServicePool.hpp +++ b/inc/ServicePool.hpp @@ -1,6 +1,7 @@ #ifndef ECSS_SERVICES_SERVICEPOOL_HPP #define ECSS_SERVICES_SERVICEPOOL_HPP +#include "Services/LargePacketTransferService.hpp" #include "Services/RequestVerificationService.hpp" #include "Services/TimeManagementService.hpp" #include "Services/EventReportService.hpp" @@ -26,6 +27,7 @@ public: EventActionService eventAction; TestService testService; ParameterService parameterManagement; + LargePacketTransferService largePacketTransferService; FunctionManagementService functionManagement; /** diff --git a/inc/Services/LargePacketTransferService.hpp b/inc/Services/LargePacketTransferService.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7ed7d997ebcea0009193ebeb52d823001c38cab2 --- /dev/null +++ b/inc/Services/LargePacketTransferService.hpp @@ -0,0 +1,82 @@ +#ifndef ECSS_SERVICES_LARGEPACKETTRANSFERSERVICE_HPP +#define ECSS_SERVICES_LARGEPACKETTRANSFERSERVICE_HPP + +#include "Service.hpp" +#include <etl/String.hpp> + +/** + * Implementation of the ST[13] large packet transfer service + * The goal of this service is to help in splitting data packages that exceed the standard's + * maximum data size + * + * Note: More information can be found in the standards' manual, in p. 526-528 and in p. 229-236 + */ + +class LargePacketTransferService : public Service { +public: + + /** + * Default constructor since only functions will be used. + */ + LargePacketTransferService() { + serviceType = 13; + } + + /** + * Function that handles the first part of the download report + * @param largeMessageTransactionIdentifier The identifier of the large packet + * @param partSequenceNumber The identifier of the part of the large packet + * @param string The data contained in this part of the large packet + */ + void firstDownlinkPartReport(uint16_t + largeMessageTransactionIdentifier, uint16_t partSequenceNumber, + const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string); + + /** + * Function that handles the n-2 parts of tbe n-part download report + * @param largeMessageTransactionIdentifier The identifier of the large packet + * @param partSequenceNumber The identifier of the part of the large packet + * @param string The data contained in this part of the large packet + */ + void intermediateDownlinkPartReport(uint16_t + largeMessageTransactionIdentifier, + uint16_t partSequenceNumber, + const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string); + + /** + * Function that handles the last part of the download report + * @param largeMessageTransactionIdentifier The identifier of the large packet + * @param partSequenceNumber The identifier of the part of the large packet + * @param string The data contained in this part of the large packet + */ + void lastDownlinkPartReport(uint16_t + largeMessageTransactionIdentifier, uint16_t partSequenceNumber, + const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string); + + + // The three uplink functions should handle a TC request to "upload" data. Since there is not + // a createTC function ready, I just return the given string. + // @TODO: Modify these functions properly + /** + * Function that handles the first part of the uplink request + * @param string This will change when these function will be modified + */ + String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> + firstUplinkPart(const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string); + + /** + * Function that handles the n-2 parts of tbe n-part uplink request + * @param string This will change when these function will be modified + */ + String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> + intermediateUplinkPart(const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string); + + /** + * Function that handles the last part of the uplink request + * @param string This will change when these function will be modified + */ + String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> + lastUplinkPart(const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string); +}; + +#endif // ECSS_SERVICES_LARGEPACKETTRANSFERSERVICE_HPP diff --git a/src/Message.cpp b/src/Message.cpp index 409e65e4e18ae303c8cbcac02422172615943184..0127ecf679d0bdf93600413653eea9878f20690e 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -145,6 +145,7 @@ void Message::readString(uint8_t *string, uint16_t size) { ASSERT_REQUEST(size < ECSS_MAX_STRING_SIZE, ErrorHandler::StringTooShort); memcpy(string, data + readPosition, size); + string[size] = '\0'; // todo: Use that for now to avoid problems. Later to be removed readPosition += size; } diff --git a/src/Services/LargePacketTransferService.cpp b/src/Services/LargePacketTransferService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fedfec8f97b65dd9264502c8ef45c8e801e4e084 --- /dev/null +++ b/src/Services/LargePacketTransferService.cpp @@ -0,0 +1,55 @@ +#include <Services/LargePacketTransferService.hpp> +#include "Message.hpp" +#include <etl/String.hpp> + +void LargePacketTransferService::firstDownlinkPartReport(uint16_t + largeMessageTransactionIdentifier, + uint16_t partSequenceNumber, + const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string) { + // TM[13,1] + + Message report = createTM(1); + report.appendUint16(largeMessageTransactionIdentifier); // large message transaction identifier + report.appendUint16(partSequenceNumber); // part sequence number + report.appendOctetString(string); // fixed octet-string + storeMessage(report); +} + +void LargePacketTransferService::intermediateDownlinkPartReport(uint16_t + largeMessageTransactionIdentifier, uint16_t partSequenceNumber, const + String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string) { + // TM[13,2] + Message report = createTM(2); + report.appendUint16(largeMessageTransactionIdentifier); // large message transaction identifier + report.appendUint16(partSequenceNumber); // part sequence number + report.appendOctetString(string); // fixed octet-string + storeMessage(report); +} + +void LargePacketTransferService::lastDownlinkPartReport(uint16_t largeMessageTransactionIdentifier, + uint16_t partSequenceNumber, const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string) { + // TM[13,3] + Message report = createTM(3); + report.appendUint16(largeMessageTransactionIdentifier); // large message transaction identifier + report.appendUint16(partSequenceNumber); // part sequence number + report.appendOctetString(string); // fixed octet-string + storeMessage(report); +} + +String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> LargePacketTransferService::firstUplinkPart( + const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string) { + // TC[13,9] + return string; +} + +String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> LargePacketTransferService::intermediateUplinkPart( + const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string) { + // TC[13,10] + return string; +} + +String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> +LargePacketTransferService::lastUplinkPart(const String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> &string) { + // TC[13, 11] + return string; +} diff --git a/src/main.cpp b/src/main.cpp index 6067a82a5459d2c2137f0b8702484c7ece768791..4e5a4f4652fe4463d4d20f1586d15eb48c922ec0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,9 @@ #include "Services/FunctionManagementService.hpp" #include "Services/TimeManagementService.hpp" #include "Services/EventActionService.hpp" +#include "Services/LargePacketTransferService.hpp" #include "Services/TimeBasedSchedulingService.hpp" +#include "ServicePool.hpp" #include "Message.hpp" #include "MessageParser.hpp" #include "Helpers/CRCHelper.hpp" @@ -240,22 +242,24 @@ int main() { eventActionService.addEventActionDefinitions(eventActionDefinition); Message eventActionDefinition1(19, 1, Message::TC, 1); eventActionDefinition1.appendEnum16(0); - eventActionDefinition1.appendEnum16(2); + eventActionDefinition1.appendEnum16(3); TCdata = "hi1"; eventActionDefinition1.appendString(TCdata); eventActionService.addEventActionDefinitions(eventActionDefinition1); Message eventActionDefinition2(19, 1, Message::TC, 1); eventActionDefinition2.appendEnum16(0); - eventActionDefinition2.appendEnum16(3); + eventActionDefinition2.appendEnum16(4); TCdata = "hi2"; eventActionDefinition2.appendString(TCdata); eventActionService.addEventActionDefinitions(eventActionDefinition2); Message eventActionDefinition3(19, 5, Message::TC, 1); - eventActionDefinition3.appendUint16(2); + eventActionDefinition3.appendUint16(3); eventActionDefinition3.appendUint16(0); eventActionDefinition3.appendUint16(2); eventActionDefinition3.appendUint16(0); eventActionDefinition3.appendUint16(3); + eventActionDefinition3.appendUint16(0); + eventActionDefinition3.appendUint16(4); eventActionService.disableEventActionDefinitions(eventActionDefinition3); std::cout << "Status of position 0,1,2 should be 000:" << eventActionService @@ -270,15 +274,17 @@ int main() { eventActionDefinition5.appendUint16(0); eventActionDefinition5.appendUint16(3); eventActionService.enableEventActionDefinitions(eventActionDefinition5); - std::cout << "\nStatus of position 0,1,2 should be 111:" << eventActionService + std::cout << "\nStatus of position 0,1,2 should be 110:" << eventActionService .eventActionDefinitionArray[0].enabled << eventActionService .eventActionDefinitionArray[1].enabled << eventActionService.eventActionDefinitionArray[2].enabled; Message eventActionDefinition4(19, 2, Message::TC, 1); - eventActionDefinition4.appendUint16(1); + eventActionDefinition4.appendUint16(2); eventActionDefinition4.appendUint16(0); eventActionDefinition4.appendUint16(2); + eventActionDefinition4.appendUint16(0); + eventActionDefinition4.appendUint16(3); eventActionService.deleteEventActionDefinitions(eventActionDefinition4); std::cout << "\nPositions 0,1 empty should be 11:" << static_cast<uint16_t>(eventActionService @@ -288,7 +294,14 @@ int main() { Message eventActionDefinition6(19, 3, Message::TC, 1); eventActionService.deleteAllEventActionDefinitions(eventActionDefinition6); std::cout << "\nPositions 0,1 empty should be 1:" << static_cast<uint16_t>(eventActionService - .eventActionDefinitionArray[0].empty); + .eventActionDefinitionArray[0].empty); + + + // ST13 test + + LargePacketTransferService largePacketTransferService; + String<256> dataToTransfer = "12345678"; + largePacketTransferService.firstDownlinkPartReport(1, 1, dataToTransfer); // ST[11] test diff --git a/test/Services/LargePacketTransferService.cpp b/test/Services/LargePacketTransferService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7109ee763d620047241ac94cc0ab19a6aa73662 --- /dev/null +++ b/test/Services/LargePacketTransferService.cpp @@ -0,0 +1,71 @@ +#include <catch2/catch.hpp> +#include <Services/LargePacketTransferService.hpp> +#include <Message.hpp> +#include "ServiceTests.hpp" +#include <cstring> +#include <etl/String.hpp> + +LargePacketTransferService &lPT = Services.largePacketTransferService; + +TEST_CASE("First Downlink Part Report TM[13,1]", "[service][st13]") { + String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> string = String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> + ("12345678"); + lPT.firstDownlinkPartReport(1, 1, string); + REQUIRE(ServiceTests::hasOneMessage()); + Message report = ServiceTests::get(0); + CHECK(report.messageType == 1); + CHECK(report.serviceType == 13); + CHECK(report.readUint16() == 1); + CHECK(report.readUint16() == 1); + uint8_t string2[ECSS_MAX_FIXED_OCTET_STRING_SIZE]; + printf("%d", report.readOctetString(string2)); + auto a = String<ECSS_MAX_FIXED_OCTET_STRING_SIZE>(string2, 8); + CHECK(string.compare(a) == 0); +} + +TEST_CASE("Intermediate Downlink Part Report TM[13,2]", "[service][st13]") { + String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> string = String<ECSS_MAX_FIXED_OCTET_STRING_SIZE>( + "12345678"); + lPT.intermediateDownlinkPartReport(1, 1, string); + REQUIRE(ServiceTests::hasOneMessage()); + Message report = ServiceTests::get(0); + CHECK(report.messageType == 2); + CHECK(report.serviceType == 13); + CHECK(report.readUint16() == 1); + CHECK(report.readUint16() == 1); + uint8_t string2[ECSS_MAX_FIXED_OCTET_STRING_SIZE]; + report.readOctetString(string2); + auto a = String<ECSS_MAX_FIXED_OCTET_STRING_SIZE>(string2, 8); + CHECK(string.compare(a) == 0); +} + +TEST_CASE("Last Downlink Part Report TM[13,3]", "[service][st13]") { + String<ECSS_MAX_FIXED_OCTET_STRING_SIZE> string = String<ECSS_MAX_FIXED_OCTET_STRING_SIZE>( + "12345678"); + lPT.lastDownlinkPartReport(1, 1, string); + REQUIRE(ServiceTests::hasOneMessage()); + Message report = ServiceTests::get(0); + CHECK(report.messageType == 3); + CHECK(report.serviceType == 13); + CHECK(report.readUint16() == 1); + CHECK(report.readUint16() == 1); + uint8_t string2[ECSS_MAX_FIXED_OCTET_STRING_SIZE]; + report.readOctetString(string2); + auto a = String<ECSS_MAX_FIXED_OCTET_STRING_SIZE>(string2, 8); + CHECK(string.compare(a) == 0); +} + +TEST_CASE("First Uplink Part TC[13,9]", "[service][st13]") { + String<256> string = "12345678"; + CHECK(string.compare(lPT.firstUplinkPart(string)) == 0); +} + +TEST_CASE("Intermediate Uplink Part TC[13,10]", "[service][st13]") { + String<256> string = "12345678"; + CHECK(string.compare(lPT.intermediateUplinkPart(string)) == 0); +} + +TEST_CASE("Last Uplink Part TC[13,11]", "[service][st13]") { + String<256> string = "12345678"; + CHECK(string.compare(lPT.lastUplinkPart(string)) == 0); +}