5#include <ChimeraTK/SystemTags.h>
16 PriorityMode mode, std::unordered_set<std::string> tagsToAggregate,
17 const std::unordered_set<std::string>& outputTags, std::string warnMixedMessage)
18 :
ApplicationModule(owner,
".", description, outputTags), _output(this, name), _mode(mode),
19 _tagsToAggregate(std::move(tagsToAggregate)), _warnMixedMessage(std::move(warnMixedMessage)) {
23 throw ChimeraTK::logic_error(
24 "StatusAggregator: List of tagsToAggregate is currently limited to one tag (see #13256).");
38 std::set<std::string> inputPathsSet;
40 std::set<std::string> anotherStatusAgregatorInputSet;
42 std::map<std::string, std::string> statusToMessagePathsMap;
44 auto scanModel = [&](
auto proxy) {
46 auto* staAggPtr =
dynamic_cast<StatusAggregator*
>(&proxy.getApplicationModule());
47 if(staAggPtr !=
nullptr) {
48 if(staAggPtr ==
this) {
57 if(outputNode.getTags().find(tagToAgregate) == outputNode.getTags().end()) {
62 inputPathsSet.insert(staAggPtr->_output._status.getModel().getFullyQualifiedPath());
64 statusToMessagePathsMap[staAggPtr->_output._status.getModel().getFullyQualifiedPath()] =
65 staAggPtr->_output._message.getModel().getFullyQualifiedPath();
67 for(
auto& anotherStatusAgregatorInput : staAggPtr->_inputs) {
68 anotherStatusAgregatorInputSet.insert(
69 anotherStatusAgregatorInput._status.getModel().getFullyQualifiedPath());
81 auto tags = proxy.getTags();
89 if(tags.find(ChimeraTK::SystemTags::statusOutput) != tags.end()) {
96 if(tags.find(tagToAgregate) == tags.end()) {
100 inputPathsSet.insert(proxy.getFullyQualifiedPath());
103 std::string fqn = proxy.getFullyQualifiedPath();
105 statusToMessagePathsMap[proxy.getFullyQualifiedPath()] = fqn +
"_message";
111 model.visit(scanModel, ChimeraTK::Model::keepApplicationModules || ChimeraTK::Model::keepProcessVariables,
112 ChimeraTK::Model::breadthFirstSearch, ChimeraTK::Model::keepOwnership);
114 for(
const auto& pathToBeRemoved : anotherStatusAgregatorInputSet) {
115 inputPathsSet.erase(pathToBeRemoved);
118 for(
const auto& pathToBeAggregated : inputPathsSet) {
120 this, pathToBeAggregated, pathToBeAggregated, std::unordered_set<std::string>{
tagInternalVars});
121 if(!statusToMessagePathsMap[pathToBeAggregated].empty()) {
122 _inputs.back().setMessageSource(statusToMessagePathsMap[pathToBeAggregated]);
128 using Status = StatusOutput::Status;
131 static const std::map<PriorityMode, std::map<Status, int32_t>> map_priorities{
132 {
PriorityMode::fwko, {{Status::OK, 1}, {Status::FAULT, 3}, {Status::OFF, 0}, {Status::WARNING, 2}}},
133 {
PriorityMode::fwok, {{Status::OK, 0}, {Status::FAULT, 3}, {Status::OFF, 1}, {Status::WARNING, 2}}},
134 {
PriorityMode::ofwk, {{Status::OK, 0}, {Status::FAULT, 2}, {Status::OFF, 3}, {Status::WARNING, 1}}},
137 return map_priorities.at(
_mode).at(status);
144 std::map<TransferElementID, StatusWithMessageInput*> inputsMap;
146 inputsMap[x._status.getId()] = &x;
147 if(x.hasMessageSource) {
148 inputsMap[x._message.getId()] = &x;
155 StatusOutput::Status status{StatusOutput::Status::FAULT};
165 bool statusSet =
false;
167 for(
auto& inputPair :
_inputs) {
175 if(!statusSet || prio > statusPrio ||
176 (input == status && statusOrigin !=
nullptr &&
177 input.getVersionNumber() < statusOrigin->
_status.getVersionNumber())) {
179 statusOrigin = &inputPair;
183 else if(prio == -1) {
184 if(statusPrio == -1 && input != status) {
185 status = StatusOutput::Status::WARNING;
186 statusOrigin =
nullptr;
199 assert(status == StatusOutput::Status::WARNING);
203 if(status != StatusOutput::Status::OK) {
205 auto msg = statusOrigin->getMessage();
215 auto change = rag.readAny();
216 auto f = inputsMap.find(change);
217 if(f != inputsMap.end()) {
218 auto* varPair = f->second;
219 if(!varPair->update(change)) {
225 if(change ==
_debug.getId()) {
227 myLog <<
"StatusAggregtor (";
236 myLog <<
"fw_warn_mixed";
243 <<
" debug info:" << std::endl;
244 for(
auto& inputPair :
_inputs) {
246 myLog << static_cast<VariableNetworkNode>(input).getQualifiedName() <<
" = " << input;
247 if(inputPair.hasMessageSource) {
249 << std::string(inputPair._message);
255 myLog <<
"debug info finished." << std::endl;
264 return DataValidity::ok;
Logger::StreamProxy logger(Logger::Severity severity)
Convenicene function to obtain a logger stream with the given Severity.
ChimeraTK::Model::ApplicationModuleProxy getModel()
Return the application model proxy representing this module.
void addTag(const std::string &tag)
Add a tag.
Model::ProcessVariableProxy getModel() const
std::string getFullyQualifiedPath() const
Return the fully qualified path.
std::string getQualifiedName() const override
Get the fully qualified name of the module instance, i.e.
EntityOwner * _owner
Owner of this instance.
ChimeraTK::ReadAnyGroup readAnyGroup()
Create a ChimeraTK::ReadAnyGroup for all readable variables in this Module.
Class describing a node of a variable network.
constexpr bool isApplicationModule(const PROPERTY_OR_PROXY &)
constexpr bool isVariable(const PROPERTY_OR_PROXY &)
InvalidityTracer application module.
The StatusAggregator collects results of multiple StatusMonitor instances and aggregates them into a ...
VoidInput _debug
Allow runtime debugging.
StatusAggregator()=default
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
PriorityMode
Possible status priority modes used during aggregation of unequal Status values.
@ fw_warn_mixed
fault - warning - ok or off, mixed state of ok or off results in warning
@ ofwk
off - fault - warning - ok
@ fwko
fault - warning - ok - off
@ fwok
fault - warning - off - ok
void populateStatusInput()
Recursivly search for StatusMonitors and other StatusAggregators.
void setWarnMixedMessage(std::string message)
Set a custom message for the warn mixed state.
std::vector< StatusWithMessageInput > _inputs
All status inputs to be aggregated.
int getPriority(StatusOutput::Status status) const
Convert Status value into a priority (high integer value = high priority), depending on chosen Priori...
PriorityMode _mode
Priority mode used in aggregation.
StatusWithMessage _output
The aggregated status output.
DataValidity getDataValidity() const override
Return the data validity flag.
std::string _warnMixedMessage
Error message for the warn_mixed condition.
static constexpr auto tagInternalVars
Reserved tag which is used to mark internal variables which should not be visible in the virtual hier...
std::unordered_set< std::string > _tagsToAggregate
List of tags to aggregate.
static constexpr auto tagAggregatedStatus
Reserved tag which is used to mark aggregated status outputs (need to stop searching further down the...
static constexpr auto tagStatusHasMessage
Reserved tag which is used to mark presense of the message output.
void writeIfDifferent(StatusOutput::Status status, std::string message)
ScalarOutput< std::string > _message
void writeOkIfDifferent()