diff --git a/inc/Services/Parameter.hpp b/inc/Services/Parameter.hpp index 12f8f1bb3b134870cb3bf46f16e315067733ec26..9cf9a01583ad83c23816fb5785c7a58eece8dfc6 100644 --- a/inc/Services/Parameter.hpp +++ b/inc/Services/Parameter.hpp @@ -2,10 +2,12 @@ #define ECSS_SERVICES_PARAMETER_HPP #include "etl/bitset.h" +#include "etl/String.hpp" // Number of binary flags in every parameter. Final number TBD. #define NUM_OF_FLAGS 3 - +// Maximum etl::string length in bytes +#define MAX_STRING_LENGTH 5 /** * Implementation of a Parameter field, as specified in ECSS-E-ST-70-41C. * Fully compliant with the standards requirements, while adding some small, @@ -23,7 +25,8 @@ * @typedef Flags: container for the binary flags */ typedef uint16_t ParamId; -//typedef etl::variant<bool, uint8_t, int32_t, float> ValueType; +//typedef uint32_t ValueType; +//#typedef ; typedef etl::bitset<NUM_OF_FLAGS> Flags; /** @@ -54,24 +57,59 @@ typedef etl::bitset<NUM_OF_FLAGS> Flags; * @public getCurrentValue(): Gets the current value of the parameter * @public getPTC(), getPFC(): Returns the PFC and PTC of the parameter */ -template <typename ValueType> class Parameter { + +class ParameterBase { +protected: uint8_t ptc; uint8_t pfc; - void(*ptr)(ValueType*); + uint8_t sizeInBytes; + void* valuePtr; Flags flags; - ValueType currentValue = 0; +public: + uint8_t getPTC(); + + void setFlags(const char* flags); + + uint8_t getPFC(); + + virtual String<MAX_STRING_LENGTH> getValueAsString() = 0; + + template <typename ValueType> + void setCurrentValue(ValueType newVal) { + // set the value only if the parameter can be updated manually + if (flags[1]) { + *reinterpret_cast<ValueType*>(valuePtr) = newVal; + } + } +}; - public: - Parameter<ValueType>(uint8_t newPtc, uint8_t newPfc, const ValueType& initialValue, void(*newPtr)(ValueType*)); +template <typename ValueType> +class Parameter : public ParameterBase { + void (* ptr)(ValueType*); - void setCurrentValue(const ValueType& newVal); - void setFlags(const char* flags); + ValueType currentValue; - ValueType getCurrentValue(); - uint8_t getPTC(); +public: + Parameter(uint8_t newPtc, uint8_t newPfc, ValueType initialValue = 0, void(* newPtr)(ValueType*) = nullptr) { + ptc = newPtc; + pfc = newPfc; + ptr = newPtr; + sizeInBytes = sizeof(initialValue); + valuePtr = static_cast<void*>(¤tValue); + // see Parameter.hpp for explanation on flags + // by default: no update priority, manual and automatic update available - uint8_t getPFC(); + if (ptr != nullptr) { + (*ptr)(¤tValue); // call the update function for the initial value + } else { + currentValue = initialValue; + } + } + String<MAX_STRING_LENGTH> getValueAsString() override { + String<MAX_STRING_LENGTH> contents(reinterpret_cast<uint8_t*>(¤tValue), sizeInBytes); + return contents; + } }; diff --git a/inc/Services/ParameterService.hpp b/inc/Services/ParameterService.hpp index 3d473103009f0da4bfd90ceb88121edee80e6226..d7f64751d4abf5f5e18192890c77d679a678fcd4 100644 --- a/inc/Services/ParameterService.hpp +++ b/inc/Services/ParameterService.hpp @@ -27,7 +27,7 @@ class ParameterService : public Service { private: - etl::map<ParamId, Parameter, ECSS_ST_20_MAX_PARAMETERS> paramsList; + etl::map<ParamId, ParameterBase*, ECSS_ST_20_MAX_PARAMETERS> paramsList; public: /** @@ -43,7 +43,7 @@ public: * @param param: the parameter field to be included * @param flags: the flags to be set for this field (see Parameter.hpp) */ - void addNewParameter(uint16_t id, Parameter param, const char* flags = "110"); + void addNewParameter(uint16_t id, ParameterBase* param, const char* flags = "110"); /** * This function receives a TC[20, 1] packet and returns a TM[20, 2] packet diff --git a/src/Services/Parameter.cpp b/src/Services/Parameter.cpp index 9a96fe4eb18eaf8121ab9deb0165f1c7fa4a8a31..f1410d910314931e536b24b49945d3cf9dc2c9fe 100644 --- a/src/Services/Parameter.cpp +++ b/src/Services/Parameter.cpp @@ -1,45 +1,13 @@ #include "Services/Parameter.hpp" -template <typename ValueType> -Parameter<ValueType>::Parameter(uint8_t newPtc, uint8_t newPfc, const ValueType& initialValue, void(*newPtr)(ValueType*)) { - ptc = newPtc; - pfc = newPfc; - ptr = newPtr; - - // see Parameter.hpp for explanation on flags - // by default: no update priority, manual and automatic update available - - if (ptr != nullptr) { - (*ptr)(¤tValue); // call the update function for the initial value - } else { - currentValue = initialValue; - } -} - -template <typename ValueType> -void Parameter<ValueType>::setCurrentValue(const ValueType& newVal) { - // set the value only if the parameter can be updated manually - if (flags[1]) { - currentValue = newVal; - } -} - -template <typename ValueType> -ValueType Parameter<ValueType>::getCurrentValue() { - return currentValue; -} -template <typename ValueType> -uint8_t Parameter<ValueType>::getPTC() { +uint8_t ParameterBase::getPTC() { return ptc; } -template <typename ValueType> -uint8_t Parameter<ValueType>::getPFC() { +uint8_t ParameterBase::getPFC() { return pfc; } -template <typename ValueType> -void Parameter<ValueType>::setFlags(const char* flags) { +void ParameterBase::setFlags(const char* flags) { this->flags = Flags(flags); -} - +} \ No newline at end of file diff --git a/src/Services/ParameterService.cpp b/src/Services/ParameterService.cpp index 2ac5d101a779f2090490fd78d18141bc5bfb9655..aff371d1580ba53aeea6d15fd17a92f2c7d50042 100644 --- a/src/Services/ParameterService.cpp +++ b/src/Services/ParameterService.cpp @@ -7,14 +7,14 @@ ParameterService::ParameterService() { // addNewParameter(3, 14); } -void ParameterService::addNewParameter(uint16_t id, Parameter param, const char* flags) { +void ParameterService::addNewParameter(uint16_t id, ParameterBase* param, const char* flags) { if (paramsList.full()) { ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::MapFull); return; } else { if (paramsList.find(id) == paramsList.end()) { - param.setFlags(flags); + param->setFlags(flags); paramsList.insert(std::make_pair(id, param)); return; } @@ -26,7 +26,7 @@ void ParameterService::addNewParameter(uint16_t id, Parameter param, const char* } void ParameterService::reportParameterIds(Message& paramIds) { - etl::vector<std::pair<uint16_t, ValueType>, ECSS_ST_20_MAX_PARAMETERS> validParams; + etl::vector<std::pair<uint16_t, String<MAX_STRING_LENGTH>>, ECSS_ST_20_MAX_PARAMETERS> validParams; Message reqParam(20, 2, Message::TM, 1); // empty TM[20, 2] parameter report message @@ -50,7 +50,8 @@ void ParameterService::reportParameterIds(Message& paramIds) { uint16_t currId = paramIds.readUint16(); if (paramsList.find(currId) != paramsList.end()) { - std::pair<uint16_t, ValueType> p = std::make_pair(currId, paramsList.at(currId).getCurrentValue()); + std::pair<uint16_t, String<MAX_STRING_LENGTH>> p = std::make_pair(currId, paramsList.at(currId) + ->getValueAsString()); // pair containing the parameter's ID as first element and its current value as second validParams.push_back(p); validIds++; @@ -65,7 +66,7 @@ void ParameterService::reportParameterIds(Message& paramIds) { for (auto i: validParams) { reqParam.appendUint16(i.first); // append the parameter ID - reqParam.appendUint32(i.second); // and its value + reqParam.appendString(i.second); // and its value } storeMessage(reqParam); // then store the message @@ -88,7 +89,7 @@ void ParameterService::setParameterIds(Message& newParamValues) { uint16_t currId = newParamValues.readUint16(); // the parameter is checked for read-only status and manual update availability if (paramsList.find(currId) != paramsList.end()) { - paramsList.at(currId).setCurrentValue(newParamValues.readUint32()); + paramsList.at(currId)->setCurrentValue(newParamValues.readUint32()); } else { ErrorHandler::reportError(newParamValues, diff --git a/test/Services/ParameterService.cpp b/test/Services/ParameterService.cpp index ee678cd5a5998f3a256e9283fb0f2362a14bbee8..86987f9e08d469473bfd2bb9dae342bd64873aaf 100644 --- a/test/Services/ParameterService.cpp +++ b/test/Services/ParameterService.cpp @@ -5,38 +5,34 @@ ParameterService& pserv = Services.parameterManagement; -void foo(ValueType* bar) { // sample function - *bar = 0xDEADBEEF; -} - TEST_CASE("Parameter Service - General") { SECTION("Addition to full map") { - Parameter param0 = Parameter(3, 14); - Parameter param1 = Parameter(1, 7, 12); - Parameter param2 = Parameter(4, 12, 3, nullptr); - Parameter param3 = Parameter(12, 3, 6, &foo); - Parameter param4 = Parameter(15, 7, 3, &foo); + Parameter<int> param0 = Parameter<int>(3, 14); + Parameter<int> param1 = Parameter<int>(1, 7, 12); + Parameter<int> param2 = Parameter<int>(4, 12, 3, nullptr); + Parameter<int> param3 = Parameter<int>(12, 3, 6); + Parameter<int> param4 = Parameter<int>(15, 7, 3); - Parameter param5 = Parameter(15, 5, 4); + Parameter<int> param5 = Parameter<int>(15, 5, 4); - pserv.addNewParameter(0, param0); - pserv.addNewParameter(1, param1); - pserv.addNewParameter(2, param2); - pserv.addNewParameter(3, param3); - pserv.addNewParameter(4, param4); + pserv.addNewParameter(0, static_cast<ParameterBase*>(¶m0)); + pserv.addNewParameter(1, static_cast<ParameterBase*>(¶m1)); + pserv.addNewParameter(2, static_cast<ParameterBase*>(¶m2)); + pserv.addNewParameter(3, static_cast<ParameterBase*>(¶m3)); + pserv.addNewParameter(4, static_cast<ParameterBase*>(¶m4)); - pserv.addNewParameter(5, param5); // addNewParameter should return false + pserv.addNewParameter(5, static_cast<ParameterBase*>(¶m5)); // addNewParameter should return false CHECK(ServiceTests::thrownError(ErrorHandler::InternalErrorType::MapFull)); ServiceTests::reset(); Services.reset(); // reset all services } SECTION("Addition of already existing parameter") { - Parameter param0 = Parameter(1, 3); - pserv.addNewParameter(0, param0); + Parameter<int> param0 = Parameter<int>(1, 3); + pserv.addNewParameter(0, static_cast<ParameterBase*>(¶m0)); - pserv.addNewParameter(0, param0); + pserv.addNewParameter(0, static_cast<ParameterBase*>(¶m0)); CHECK(ServiceTests::thrownError(ErrorHandler::InternalErrorType::ExistingParameterId)); ServiceTests::reset(); Services.reset(); @@ -69,12 +65,12 @@ TEST_CASE("Parameter Report Subservice") { } SECTION("Faulty instruction handling") { - Parameter param0 = Parameter(3, 14); - Parameter param1 = Parameter(1, 7, 12); - Parameter param2 = Parameter(4, 12, 3, nullptr); - pserv.addNewParameter(0, param0); - pserv.addNewParameter(1, param1); - pserv.addNewParameter(2, param2); + Parameter<int> param0 = Parameter<int>(3, 14); + Parameter<int> param1 = Parameter<int>(1, 7, 12); + Parameter<int> param2 = Parameter<int>(4, 12, 3, nullptr); + pserv.addNewParameter(0, static_cast<ParameterBase*>(¶m0)); + pserv.addNewParameter(1, static_cast<ParameterBase*>(¶m1)); + pserv.addNewParameter(2, static_cast<ParameterBase*>(¶m2)); Message request(20, 1, Message::TC, 1); request.appendUint16(2); // number of requested IDs @@ -117,12 +113,12 @@ TEST_CASE("Parameter Report Subservice") { TEST_CASE("Parameter Setting Subservice") { SECTION("Faulty Instruction Handling Test") { - Parameter param0 = Parameter(3, 14); - Parameter param1 = Parameter(1, 7, 12); - Parameter param2 = Parameter(4, 12, 3, nullptr); - pserv.addNewParameter(0, param0); - pserv.addNewParameter(1, param1); - pserv.addNewParameter(2, param2); + Parameter<int> param0 = Parameter<int>(3, 14); + Parameter<int> param1 = Parameter<int>(1, 7, 12); + Parameter<int> param2 = Parameter<int>(4, 12, 3, nullptr); + pserv.addNewParameter(0, static_cast<ParameterBase*>(¶m0)); + pserv.addNewParameter(1, static_cast<ParameterBase*>(¶m1)); + pserv.addNewParameter(2, static_cast<ParameterBase*>(¶m2)); Message setRequest(20, 3, Message::TC, 1); setRequest.appendUint16(2); // total number of IDs @@ -154,8 +150,8 @@ TEST_CASE("Parameter Setting Subservice") { } SECTION("Attempt to set parameter with no manual update availability") { - Parameter param1 = Parameter(1, 7, 12); - pserv.addNewParameter(1, param1, "100"); + Parameter<int> param1 = Parameter<int>(1, 7, 12); + pserv.addNewParameter(1, static_cast<ParameterBase*>(¶m1), "100"); Message setRequest = Message(20, 3, Message::TC, 1); setRequest.appendUint16(1);