Skip to content
Snippets Groups Projects
Commit 2b51a94e authored by kongr45gpen's avatar kongr45gpen Committed by athatheo
Browse files

Add notifying parameter callbacks

parent 21283376
No related branches found
No related tags found
No related merge requests found
#ifndef ECSS_SERVICES_NOTIFYPARAMETER_HPP
#define ECSS_SERVICES_NOTIFYPARAMETER_HPP
#include <etl/optional.h>
#include <functional>
#include "Parameter.hpp"
/**
* A Notifying parameter will call a function whenever its value is written to.
*
* This is useful for updating the state of things when a parameter is changed,
* for example to disable/enable peripherals, to make configuration changes etc.
*
* @warning Calling NotifyParameter::setValue will *not* call the notifier
* function. You should use setValueLoudly for this purpose instead.
*
* @tparam DataType The data type of the parameter's value
*/
template <typename DataType>
class NotifyParameter : public Parameter<DataType> {
public:
using Notifier = std::function<void(const DataType&)>;
using Parent = Parameter<DataType>;
/**
* Constructor without a notifier function. Nothing will then happen when the parameter is updated.
*/
explicit NotifyParameter(DataType initialValue) : Parent(initialValue) {}
/**
* Constructor with a default notifier function.
*/
NotifyParameter(DataType initialValue, const Notifier& notifier) : Parent(initialValue), notifier(notifier) {}
/**
* Same as Parameter::setValue(), but also calls the NotifyParameter::notifier function, if it
* exists.
*/
inline void setValueLoudly(DataType value) {
Parent::setValue(value);
if (notifier) {
(*notifier)(Parent::currentValue);
}
}
/**
* Call the notifier if it exists, without updating the value
*/
inline void notify() {
if (notifier) {
(*notifier)(Parent::currentValue);
}
}
inline void setValueFromMessage(Message& message) override {
Parent::setValueFromMessage(message);
if (notifier) {
(*notifier)(Parent::currentValue);
}
}
/**
* Set the notifier function, to be called whenever the value of this parameter is updated.
*
* @note This function will be called even when a _parameter update_ command is received, but the
* new value is the same as the previous one. This is done so that there is an option to repair
* systems with a weird or unknown state.
* @param call Whether to also call the notifier function immediately, to ensure that a change is
* made.
*/
void setNotifier(const Notifier& _notifier, bool call=true) {
notifier = _notifier;
if (call) {
_notifier(Parent::currentValue);
}
}
/**
* Unset the notifier function, so that nothing is called when the value of this function is updated.
*/
void unsetNotifier() {
notifier.reset();
}
private:
etl::optional<Notifier> notifier;
};
#endif //ECSS_SERVICES_NOTIFYPARAMETER_HPP
......@@ -58,7 +58,7 @@ public:
*/
template <typename DataType>
class Parameter : public ParameterBase {
private:
protected:
DataType currentValue;
public:
......
#include "Helpers/NotifyParameter.hpp"
#include "Message.hpp"
#include "catch2/catch_all.hpp"
TEST_CASE("Notify Parameter: Notifier") {
int counter = 0;
NotifyParameter<uint32_t> parameter(0);
SECTION("Notifier not set") {
parameter.setValueLoudly(1);
CHECK(counter == 0);
}
parameter.setNotifier([&counter](auto) -> auto{
counter++;
});
CHECK(counter == 1);
parameter.setValueLoudly(2);
CHECK(counter == 2);
parameter.setValueLoudly(2);
CHECK(counter == 3);
parameter.unsetNotifier();
parameter.setValueLoudly(3);
CHECK(counter == 3);
}
TEST_CASE("Notify Parameter: Messages") {
int16_t storage;
NotifyParameter<uint32_t> parameter(
0, [&storage](auto v) -> auto{
storage = v;
});
Message message(0, 0, Message::TC);
message.appendUint32(184);
parameter.setValueFromMessage(message);
CHECK(storage == 184);
}
TEST_CASE("Notify Parameter: Extra functionality") {
int counter = 0;
NotifyParameter<uint32_t> parameter(0);
auto notifier = [&counter](auto) -> auto{
counter++;
};
parameter.setNotifier(notifier);
CHECK(counter == 1);
parameter.setNotifier(notifier, false);
CHECK(counter == 1);
parameter.notify();
CHECK(counter == 2);
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment