From 374faa0b5565202d503fac99a5d86932dceecb9e Mon Sep 17 00:00:00 2001 From: kongr45gpen <electrovesta@gmail.com> Date: Sat, 10 Aug 2019 00:54:40 +0300 Subject: [PATCH] Complete ECSS & CCSDS MessageParser::compose() functions --- inc/ECSS_Definitions.hpp | 6 ++++ inc/ErrorHandler.hpp | 4 +++ inc/MessageParser.hpp | 28 ++++++++++------ inc/etl/String.hpp | 19 +++++++++++ src/MessageParser.cpp | 72 +++++++++++++++++++++++++++++++++++----- 5 files changed, 110 insertions(+), 19 deletions(-) diff --git a/inc/ECSS_Definitions.hpp b/inc/ECSS_Definitions.hpp index 05ab25c7..90eec544 100644 --- a/inc/ECSS_Definitions.hpp +++ b/inc/ECSS_Definitions.hpp @@ -23,6 +23,12 @@ */ #define ECSS_MAX_MESSAGE_SIZE 1024U + +/** + * The maximum size of a regular ECSS message, plus its headers and trailing data, in bytes + */ +#define CCSDS_MAX_MESSAGE_SIZE (ECSS_MAX_MESSAGE_SIZE + 6u + 6u + 2u) + /** * The maximum size of a string to be read or appended to a Message, in bytes * diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp index 97732f38..238d685d 100644 --- a/inc/ErrorHandler.hpp +++ b/inc/ErrorHandler.hpp @@ -73,6 +73,10 @@ public: * Attempt to insert new function in a full function map (ST[08]) */ FunctionMapFull = 10, + /** + * A Message that is included within another message is too large + */ + NestedMessageTooLarge = 11, }; /** diff --git a/inc/MessageParser.hpp b/inc/MessageParser.hpp index e7ebe863..7bc486ef 100644 --- a/inc/MessageParser.hpp +++ b/inc/MessageParser.hpp @@ -51,7 +51,7 @@ public: * @param length The size of the message * @return A new object that represents the parsed message */ - Message parse(uint8_t* data, uint32_t length); + static Message parse(uint8_t* data, uint32_t length); /** * Parse data that contains the ECSS packet header, without the CCSDS space packet header @@ -60,23 +60,31 @@ public: * this great analysis: * stackoverflow.com/questions/15078638/can-i-turn-unsigned-char-into-char-and-vice-versa */ - Message parseECSSTC(String<ECSS_TC_REQUEST_STRING_SIZE> data); + static Message parseECSSTC(String<ECSS_TC_REQUEST_STRING_SIZE> data); /** * @brief Overloaded version of \ref MessageParser::parseECSSTC(String<ECSS_TC_REQUEST_STRING_SIZE> data) * @param data A uint8_t array of the TC packet data * @return Parsed message */ - Message parseECSSTC(uint8_t* data); + static Message parseECSSTC(uint8_t* data); /** - * @brief Converts a TC message to a string, appending just the ECSS header + * @brief Converts a TC or TM message to a message string, appending just the ECSS header + * @todo Add time reference, as soon as it is available and the format has been specified * @param message The Message object to be parsed to a String - * @return A String class containing the parsed TC request - * @attention The returned String has a fixed size, therefore the message size is considered - * fixed and equal to the ECSS_TC_REQUEST_STRING_SIZE definition. + * @param size The wanted size of the message (including the headers). Messages larger than \ref size display an + * error. Messages smaller than \ref size are padded with zeros. When `size = 0`, there is no size limit. + * @return A String class containing the parsed Message */ - String<ECSS_TC_REQUEST_STRING_SIZE> createECSSTC(Message& message); + static String<CCSDS_MAX_MESSAGE_SIZE> composeECSS(const Message& message, uint16_t size = 0u); // Ignore-MISRA + + /** + * @brief Converts a TC or TM message to a packet string, appending the ECSS and then the CCSDS header + * @param message The Message object to be parsed to a String + * @return A String class containing the parsed Message + */ + static String<CCSDS_MAX_MESSAGE_SIZE> compose(const Message& message); private: /** @@ -88,7 +96,7 @@ private: * @param length The size of the header * @param message The Message to modify based on the header */ - void parseECSSTCHeader(const uint8_t* data, uint16_t length, Message& message); + static void parseECSSTCHeader(const uint8_t* data, uint16_t length, Message& message); /** * Parse the ECSS Telemetry packet secondary header @@ -99,7 +107,7 @@ private: * @param length The size of the header * @param message The Message to modify based on the header */ - void parseECSSTMHeader(const uint8_t* data, uint16_t length, Message& message); + static void parseECSSTMHeader(const uint8_t* data, uint16_t length, Message& message); }; #endif // ECSS_SERVICES_MESSAGEPARSER_HPP diff --git a/inc/etl/String.hpp b/inc/etl/String.hpp index 11c04b67..d393c676 100644 --- a/inc/etl/String.hpp +++ b/inc/etl/String.hpp @@ -56,6 +56,25 @@ public: */ String(const char* text) // NOLINTNEXTLINE(google-explicit-constructor) : etl::string<MAX_SIZE>(text) {} + + using etl::istring::append; // Use the append function from the parent + + /** + * Append a specified with of bytes from a uint8_t array to the String + * @details The array does NOT need to be null-terminated + * @param data The characters to append + * @param n The number of characters that \ref data contains + * @return This string + */ + String& append(const uint8_t* data, size_t n) { + etl::string<MAX_SIZE>::append(reinterpret_cast<const char*>(data), n); + return *this; + } + +// String& append(const String<MAX_SIZE> & str) { +// etl::string<MAX_SIZE>::append(str); +// return *this; +// } }; #endif // ECSS_SERVICES_ETL_STRING_HPP diff --git a/src/MessageParser.cpp b/src/MessageParser.cpp index b300816b..2c6534e7 100644 --- a/src/MessageParser.cpp +++ b/src/MessageParser.cpp @@ -76,8 +76,6 @@ void MessageParser::parseECSSTCHeader(const uint8_t* data, uint16_t length, Mess uint8_t serviceType = data[1]; uint8_t messageType = data[2]; - // todo: Fix this parsing function, because it assumes PUS header in data, which is not true - // with the current implementation ErrorHandler::assertRequest(pusVersion == 2U, message, ErrorHandler::UnacceptableMessage); // Remove the length of the header @@ -106,18 +104,74 @@ Message MessageParser::parseECSSTC(uint8_t* data) { return message; } -String<ECSS_TC_REQUEST_STRING_SIZE> MessageParser::createECSSTC(Message& message) { - uint8_t tempString[ECSS_TC_REQUEST_STRING_SIZE] = {0}; +String<CCSDS_MAX_MESSAGE_SIZE> MessageParser::composeECSS(const Message& message, uint16_t size) { + uint8_t header[5]; - tempString[0] = ECSS_PUS_VERSION << 4; // Assign the pusVersion = 2 - tempString[1] = message.serviceType; - tempString[2] = message.messageType; - memcpy(tempString + 5, message.data, ECSS_TC_REQUEST_STRING_SIZE - 5); - String<ECSS_TC_REQUEST_STRING_SIZE> dataString(tempString); + if (message.packetType == Message::TC) { + header[0] = ECSS_PUS_VERSION << 4U; // Assign the pusVersion = 2 + header[1] = message.serviceType; + header[2] = message.messageType; + header[3] = 0; + header[4] = 0; + } else { + header[0] = ECSS_PUS_VERSION << 4U; // Assign the pusVersion = 2 + header[1] = message.serviceType; + header[2] = message.messageType; + header[3] = static_cast<uint8_t>(message.messageTypeCounter >> 8U); + header[4] = static_cast<uint8_t>(message.messageTypeCounter & 0xffU); + } + + String<CCSDS_MAX_MESSAGE_SIZE> dataString(header, 5); + dataString.append(message.data, message.dataSize); + + // Make sure to reach the requested size + if (size != 0) { + if (dataString.size() > size) { + // Message overflow + ErrorHandler::reportInternalError(ErrorHandler::NestedMessageTooLarge); + } else if (dataString.size() < size) { + // Append some 0s + dataString.append(size - dataString.size(), 0); + } else { + // The message has an equal size to the requested one - do nothing + } + } return dataString; } +String<CCSDS_MAX_MESSAGE_SIZE> MessageParser::compose(const Message& message) { + uint8_t header[6]; + + // First, compose the ECSS part + String<CCSDS_MAX_MESSAGE_SIZE> ecssMessage = MessageParser::composeECSS(message); + + // Sanity check that there is enough space for the string + ASSERT_INTERNAL((ecssMessage.size() + 6U) <= CCSDS_MAX_MESSAGE_SIZE, ErrorHandler::StringTooLarge); + + // Parts of the header + uint16_t packetId = 0; // TODO: Add the APID here + packetId |= (1U << 11U); // Secondary header flag + packetId |= (message.packetType == Message::TC) ? (1U << 12U) : (0U); // Ignore-MISRA + uint16_t packetSequenceControl = message.packetSequenceCount; + uint16_t packetDataLength = ecssMessage.size(); + + // Compile the header + header[0] = packetId >> 8U; + header[1] = packetId & 0xffU; + header[2] = packetSequenceControl >> 8U; + header[3] = packetSequenceControl & 0xffU; + header[4] = packetDataLength >> 8U; + header[5] = packetDataLength & 0xffU; + + // Compile the final message by appending the header + String<CCSDS_MAX_MESSAGE_SIZE> ccsdsMessage(header, 6); + ccsdsMessage.append(ecssMessage); + + return ccsdsMessage; +} + + void MessageParser::parseECSSTMHeader(const uint8_t* data, uint16_t length, Message& message) { ErrorHandler::assertRequest(length >= 5, message, ErrorHandler::UnacceptableMessage); -- GitLab