#ifndef ECSS_SERVICES_PARAMETER_HPP #define ECSS_SERVICES_PARAMETER_HPP #include "etl/String.hpp" #include "Message.hpp" #include "ECSS_Definitions.hpp" /** * Implementation of a Parameter field, as specified in ECSS-E-ST-70-41C. * * @author Grigoris Pavlakis <grigpavl@ece.auth.gr> * @author Athanasios Theocharis <athatheoc@gmail.com> * * @section Introduction * The Parameter class implements a way of storing and updating system parameters * of arbitrary size and type, while avoiding std::any and dynamic memory allocation. * It is split in two distinct parts: * 1) an abstract \ref ParameterBase class which provides a * common data type used to create any pointers to \ref Parameter objects, as well as * virtual functions for accessing the parameter's data part, and * 2) a templated \ref Parameter used to store any type-specific parameter information, * such as the actual data field where the parameter's value will be stored. * * @section Architecture Rationale * The ST[20] Parameter service is implemented with the need of arbitrary type storage * in mind, while avoiding any use of dynamic memory allocation, a requirement for use * in embedded systems. Since lack of Dynamic Memory Access precludes usage of stl::any * and the need for truly arbitrary (even for template-based objects like etl::string) type storage * would exclude from consideration constructs like etl::variant due to limitations on * the number of supported distinct types, a custom solution was needed. * Furthermore, the \ref ParameterService should provide ID-based access to parameters. */ class ParameterBase { public: /** * Given an ECSS message that contains this parameter as its first input, this loads the value from that parameter */ virtual void appendValueToMessage(Message& message) = 0; /** * Appends the parameter as an ECSS value to an ECSS Message */ virtual void setValueFromMessage(Message& message) = 0; /** * Converts the value of a parameter to a double. * * Some precision may be lost in the process. If the value is not arithmetic, * then usually 0 is returned. */ virtual double getValueAsDouble() = 0; }; /** * Implementation of a parameter containing its value. See \ref ParameterBase for more information. * @tparam DataType The type of the Parameter value. This is the type used for transmission and reception * as per the PUS. */ template <typename DataType> class Parameter : public ParameterBase { protected: DataType currentValue; public: explicit Parameter(DataType initialValue) : currentValue(initialValue) {} inline void setValue(DataType value) { currentValue = value; } inline DataType getValue() { return currentValue; } inline double getValueAsDouble() override { if constexpr (std::is_arithmetic_v<DataType>) { return static_cast<double>(currentValue); } else { return 0; } } inline void setValueFromMessage(Message& message) override { currentValue = message.read<DataType>(); }; inline void appendValueToMessage(Message& message) override { message.append<DataType>(currentValue); }; }; #endif // ECSS_SERVICES_PARAMETER_HPP